如何从地点选择器活动中检索地图快照?

Posted

技术标签:

【中文标题】如何从地点选择器活动中检索地图快照?【英文标题】:How to retrieve snapshot of map from place-picker activity? 【发布时间】:2016-12-25 06:31:01 【问题描述】:

我正在创建一个应用程序,它从 Google 地图中挑选地点并将地址存储在数据库中。我还想把选取的地方的快照存储在存储中,这样我就可以用对应的快照显示数据。

当我从地图中选择一个地点时,地点选择器活动会显示以下对话框:

在对话框中显示地址、纬度和经度以及还有快照。我知道如何获取地址和纬度。但不知道如何存储显示的快照。

这是我的方法,它检索除该图像之外的所有内容:

  //opening place picker activity.
protected void onActivityResult(int requestCode,
                                int resultCode, Intent data) 

    if (requestCode == PLACE_PICKER_REQUEST
            && resultCode == Activity.RESULT_OK) 

        final Place place = PlacePicker.getPlace(this, data);
        final CharSequence name = place.getName();
        final CharSequence address = place.getAddress();

        String attributions = (String) place.getAttributions();
        if (attributions == null) 
            attributions = "";
        
        tv4.setText(place.getLatLng().toString()+"\n"+name+"\n"+address+"\n"+attributions);


     else 
        super.onActivityResult(requestCode, resultCode, data);
    

我不知道如何获取图像并将其存储在外部或内部存储中。可能吗?我必须按照this link? 中的说明拍摄快照

编辑

我有以下活动,它正在调用地点选择器的活动:

Main2Activity.java:

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
 import android.os.Environment;
import android.support.v4.app.NavUtils;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.google.android.gms.common.GooglePlayServicesNotAvailableException;
import  com.google.android.gms.common.GooglePlayServicesRepairableException;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.places.Place;
import com.google.android.gms.location.places.ui.PlacePicker;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import android.database.Cursor;
import android.widget.EditText;
import android.widget.Toast;
import com.google.android.gms.maps.OnMapReadyCallback;

import java.io.File;
import java.io.FileOutputStream;
import java.util.Date;


public class Main2Activity extends AppCompatActivity implements OnMapReadyCallback
private static final int PLACE_PICKER_REQUEST = 1;
private TextView mName;
private TextView mAddress;
private TextView mAttributions;
private GoogleApiClient mGoogleApiClient;
public TextView tv4;
private static final LatLngBounds BOUNDS_MOUNTAIN_VIEW = new LatLngBounds(
        new LatLng(37.398160, -122.180831), new LatLng(37.430610, -121.972090));

private Toolbar toolbar;
private GoogleMap mMap;
private boolean flag = false;
DatabaseHelper myDb;
EditText newevent;
Button submit;
Button viewremainders;
@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main2);


    MapFragment mapFragment = (MapFragment) getFragmentManager() .findFragmentById(R.id.map);
    mapFragment.getMapAsync(this);



    myDb =new DatabaseHelper(this);
    newevent=(EditText)findViewById(R.id.newEvent);
    submit=(Button)findViewById(R.id.submit);
    viewremainders=(Button)findViewById(R.id.view);

    toolbar = (Toolbar)findViewById(R.id.app_bar0);
    setSupportActionBar(toolbar);

    getSupportActionBar().setHomeButtonEnabled(true);          //for back button to main activity.
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

    Button pickerButton = (Button) findViewById(R.id.pickerButton);
    tv4 = (TextView)findViewById(R.id.textView4);
    pickerButton.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View v) 
            try 
                PlacePicker.IntentBuilder intentBuilder =
                        new PlacePicker.IntentBuilder();
                intentBuilder.setLatLngBounds(BOUNDS_MOUNTAIN_VIEW);
                Intent intent = intentBuilder.build(Main2Activity.this);
                startActivityForResult(intent, PLACE_PICKER_REQUEST);


             catch (GooglePlayServicesRepairableException
                    | GooglePlayServicesNotAvailableException e) 
                e.printStackTrace();
            
        
    );

    AddData();
    viewremainders();


@Override
public void onMapReady(GoogleMap map) 


    mMap = map;


//method for adding data in Database.
public void AddData()
    submit.setOnClickListener(
            new View.OnClickListener()
                @Override
                public void onClick(View v)
                    boolean isInserted =myDb.insertData(newevent.getText().toString(),tv4.getText().toString());
                    if(isInserted==true)
                        Toast.makeText(Main2Activity.this,"Data Inserted",Toast.LENGTH_LONG).show();
                    else
                        Toast.makeText(Main2Activity.this,"Data not Inserted",Toast.LENGTH_LONG).show();

                
            
    );


//Method for view all data from database.
public void viewremainders()
    viewremainders.setOnClickListener(
            new View.OnClickListener()
                @Override
                public void onClick(View v)
                    Cursor res= myDb.getAllData();
                    if(res.getCount()==0)
                    
                        Showmessage("Error","No remainders found");
                        return;
                    
                    StringBuffer buffer=new StringBuffer();
                    while(res.moveToNext())
                    
                        buffer.append("Id : " +res.getString(0)+"\n");
                        buffer.append("Event : " +res.getString(1)+"\n");
                        buffer.append("Location : " +res.getString(2)+"\n");
                    
                    Showmessage("Data",buffer.toString());

                



            
    );


public void Showmessage(String title,String message)

    AlertDialog.Builder builder=new AlertDialog.Builder(this);
    builder.setCancelable(true);
    builder.setTitle(title);
    builder.setMessage(message);
    builder.show();



//opening place picker activity.
protected void onActivityResult(int requestCode, int resultCode, Intent data) 


    if (requestCode == PLACE_PICKER_REQUEST
            && resultCode == Activity.RESULT_OK) 

        final Place place = PlacePicker.getPlace(this, data);
        final CharSequence name = place.getName();
        final CharSequence address = place.getAddress();



        String attributions = (String) place.getAttributions();
        if (attributions == null) 
            attributions = "";
        
     //   tv4.setText(place.getLatLng().toString()+"\n"+name+"\n"+address+"\n"+attributions);  To get latitide and longitudes.
        tv4.setText(address+"\n"+attributions);





   /*     LatLngBounds selectedPlaceBounds = PlacePicker.getLatLngBounds(data);
        // move camera to selected bounds
        CameraUpdate camera = CameraUpdateFactory.newLatLngBounds(selectedPlaceBounds,0);
        mMap.moveCamera(camera);

        // take snapshot and implement the snapshot ready callback
        mMap.snapshot(new GoogleMap.SnapshotReadyCallback() 
            Bitmap bitmap=null;
            public void onSnapshotReady(Bitmap snapshot) 
                // handle snapshot here
                bitmap = snapshot;
                try 
                    FileOutputStream out = new FileOutputStream(Environment.getExternalStorageDirectory().toString()+"/ing.png");
                    bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
                    Toast.makeText(Main2Activity.this,"dsfds",Toast.LENGTH_LONG).show();
                 catch (Exception e) 
                    Toast.makeText(Main2Activity.this,e.toString(),Toast.LENGTH_SHORT).show();
                    e.printStackTrace();
                
            
        );*/



     else 
        super.onActivityResult(requestCode, resultCode, data);
    



private void capture()
    try 
        // image naming and path  to include sd card  appending name you choose for file
        String mPath = Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_MOVIES).toString();

        // create bitmap screen capture
        View v1 = getWindow().getDecorView().getRootView();
        v1.setDrawingCacheEnabled(true);
        Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
        v1.setDrawingCacheEnabled(false);

        File imageFile = new File(Environment.getExternalStorageDirectory().toString()+"/"+"lllll.jpg");

        FileOutputStream outputStream = new FileOutputStream(imageFile);
        int quality = 100;
        bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream);
        outputStream.flush();
        outputStream.close();

        openScreenshot(imageFile);
     catch (Throwable e) 
        // Several error may come out with file handling or OOM
        e.printStackTrace();
    



private void openScreenshot(File imageFile) 
    Intent intent = new Intent();
    intent.setAction(Intent.ACTION_VIEW);
    Uri uri = Uri.fromFile(imageFile);
    intent.setDataAndType(uri, "image/*");
    startActivity(intent);


//Methods for toolbar


@Override
public boolean onCreateOptionsMenu(Menu menu) 
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main2, menu);
    return true;


@Override
public boolean onOptionsItemSelected(MenuItem item) 
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) 
        return true;
    

    if(id == android.R.id.home)
        NavUtils.navigateUpFromSameTask(this);
    

    return super.onOptionsItemSelected(item);


【问题讨论】:

我们可以拍摄任何视图,但我们应该有视图参考。 但是我们不能检索这张图片作为地址和经纬度吗? @SohailZahid 你点击哪个链接发给我,我可以帮助你吗? 你可以使用任何其他的地点选择器和谷歌吗? 和谷歌?你这是什么意思? 【参考方案1】:

由于可以获取经纬度坐标,因此可以使用谷歌地图api获取地图图像。

这是示例和文档的链接:

https://developers.google.com/maps/documentation/static-maps/intro

我认为这是对话框在后台执行的操作。

如果这不起作用,或者您想要更准确的信息,我建议使用 Wireshark 来准确监控正在发送和接收的数据。

我刚刚用你的地图位置和这个网址进行了测试:

https://maps.googleapis.com/maps/api/staticmap?center=37.430610,%20-121.972090&zoom=17&size=400x400&key=[myAPIKey]

我得到了这张图片:

使用对话框中的坐标:

使用https://maps.googleapis.com/maps/api/staticmap?markers=37.414333,-122.076444&zoom=17&size=400x250&key=[myKey]

【讨论】:

嘿,谢谢你的回答。其实我想要这种类型的地图照片::: ***.com/questions/39011248/… 你有什么建议吗?我认为您的链接包含此类照片。 是的!而已!但有一个小问题。它说 The Google Maps API server rejected your request. This API project is not authorized to use this API. Please ensure this API is activated in the Google Developers Console: https://console.developers.google.com/apis/api/static_maps_backend?project=_ 是我的 API 密钥。 感谢您的回答。请解决这个问题,我会接受答案。 您可能需要不同的密钥。在该页面的左侧,有一个获取新 api 密钥的链接。试试看。应该可以为不同的目的使用两个不同的密钥。【参考方案2】:

您可以使用GoogleMap.SnapshotReadyCallback 界面。

这是一个关于如何使用它的代码示例:

SnapshotReadyCallback callback = new SnapshotReadyCallback() 
                    Bitmap bitmap;

                    @Override
                    public void onSnapshotReady(Bitmap snapshot) 
                        bitmap = snapshot;
                        try 
                            FileOutputStream out = new FileOutputStream("/some/where/to/save/it/thesnapshot.png");
                            bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
                         catch (Exception e) 
                            e.printStackTrace();
                        
                    
                ;

                map.snapshot(callback);

您可以在显示对话框时将其添加到代码中,同时保存快照。在上面的链接中阅读有关它的更多信息。

希望对你有帮助,祝你好运。

【讨论】:

嗨,兄弟,我可以在不加载 GoogleMap 片段的情况下使用 SnapshotReadyCallback 吗?我有一个 recyclerView 单元,只想显示快照【参考方案3】:

如果你想先在对话框中显示所选地点的快照,你必须将地图视图的屏幕保存到位图中。

参考此代码将您的地图视图转换为位图

Bitmap screen;
View v1 = MyView.getRootView();
v1.setDrawingCacheEnabled(true);
screen= Bitmap.createBitmap(v1.getDrawingCache());
v1.setDrawingCacheEnabled(false);

从上面的代码中,您可以获得位图,您可以通过将此位图设置为图像视图来进一步在对话框中使用它。 但请记住,您必须在生成对话框和工作线程之前执行所有操作。

【讨论】:

调用时我从这个方法传递了哪个视图? 您不必使用下面的代码,因为我已经编辑了答案并且您已经从那里获取位图,使用该位图在 imageview 中设置。 当您在任何点击时打开您的对话框,然后在同一次点击时,您必须在创建对话框之前完成所有这些操作。 请增加我的答案的计数器。 我会减少计数器。但是没有足够的声誉。【参考方案4】:

您可以查看 maps Lite。它使用 google maps api 和地图视图,但将每个视图都视为图像而不是交互式地图。您仍然可以选择缩放级别并向地图添加标记。

在你的 xml 中声明地图,就像你在普通的谷歌地图片段中一样 但包括标签 map:liteMode="true"

<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:map="http://schemas.android.com/apk/res-auto"
    android:name="com.google.android.gms.maps.MapFragment"
    android:id="@+id/map"
    android:layout_
    android:layout_
    map:cameraZoom="13"
    map:mapType="normal"
    map:liteMode="true"/>

或者如果您以编程方式创建地图,您可以使用

GoogleMapOptions options = new GoogleMapOptions().liteMode(true);

从您的 Activity 代码看来,您知道如何设置谷歌地图,因此您可以修改 onActivityResult 使其看起来像这样

protected void onActivityResult(int requestCode,
                            int resultCode, Intent data) 

if (requestCode == PLACE_PICKER_REQUEST
        && resultCode == Activity.RESULT_OK) 

    final Place place = PlacePicker.getPlace(this, data);
    final CharSequence name = place.getName();
    final CharSequence address = place.getAddress();

    String attributions = (String) place.getAttributions();
    if (attributions == null) 
        attributions = "";
    

    tv4.setText(place.getLatLng().toString()+"\n"+name+"\n"+address+"\n"+attributions);

    // Add this line to make the lite map show the location you just chose
    // and set the zoom level (10f is arbitrary)
    mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(place.getLatLng(), 10f));

 else 
    super.onActivityResult(requestCode, resultCode, data);


更多信息和引用:

如果您正在寻找更多信息,您可以从这里开始,此页面上有很多很好的链接 https://developers.google.com/maps/documentation/android-api/lite

您还可以在此处查看 Google Lite 地图演示活动: https://github.com/googlemaps/android-samples/blob/master/ApiDemos/app/src/main/java/com/example/mapdemo/LiteDemoActivity.java

这是一个很好的视频,可以很好地解释 Lite Maps:https://youtu.be/N0N1Xkc_1pU

【讨论】:

【参考方案5】:

我遇到了同样的问题。在这两种情况下,我都尝试过使用 API 密钥和服务器密钥,但我遇到了相同的错误,例如“Google Maps API 服务器拒绝了您的请求......”。最后我注意到 "Google Static Maps API" 已从控制台禁用。我只是启用,一切正常。

【讨论】:

以上是关于如何从地点选择器活动中检索地图快照?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 jQuery 日期选择器值保存到数据库并从数据库中检索

CNContactPickerViewController 与 UIToolbar

当照片选择器返回差异文件名时如何从 MediaLibrary 检索照片文件

谷歌地方选择器 API 查询应用范围的地方?

从数字选择器中删除选择

实现共享位置地点选择器,与没有地点选择器的 WhatsApp 相同,因为它已被弃用