Get GoogleMap snapshot on background

别等时光非礼了梦想. 提交于 2019-12-01 20:11:50

Please see update!

Seems it impossible to get Google Map snapshot on background on invisible MapView because map didn't even starting to load, when it is invisible. You can set correct size for invisible MapVew (e.g. based on this article), but seems it will be empty black bar with "Google" logo. Possible simplest workaround - still show MapView, but disable controls and gestures on it:

`public void onMapReady(GoogleMap googleMap) {
    mGoogleMap = googleMap;
    mGoogleMap.getUiSettings().setAllGesturesEnabled(false);
    ...
}`

or download map image via Static Map API and draw whatever you need locally on downloaded bitmap.

UPDATE:

It's possible to get Google Map snapshot on background on invisible MapView via setting it to Lite Mode on creation:

...
GoogleMapOptions options = new GoogleMapOptions()
        .compassEnabled(false)
        .mapToolbarEnabled(false)
        .camera(CameraPosition.fromLatLngZoom(KYIV,15))
        .liteMode(true);
mMapView = new MapView(this, options);
...

And it's necessary to determine the MapView size in onMapReady() via measure() and layout() calls to initiate map image loading - than, after map image loaded, it's possible get it in onMapLoaded() callback:

mMapView.setDrawingCacheEnabled(true);
mMapView.measure(View.MeasureSpec.makeMeasureSpec(mMapWidth, View.MeasureSpec.EXACTLY),
        View.MeasureSpec.makeMeasureSpec(mMapHeight, View.MeasureSpec.EXACTLY));
mMapView.layout(0, 0, mMapWidth, mMapHeight);
mMapView.buildDrawingCache(true);
Bitmap b = Bitmap.createBitmap(mMapView.getDrawingCache());  // <- that is bitmap with map image
mMapView.setDrawingCacheEnabled(false);

It is mandatory to call onCreate() on MapView object before getMapAsyhc(), otherwise no map will appear.

Full source code:

public class MainActivity extends AppCompatActivity {

    private static final String MAP_VIEW_BUNDLE_KEY = "MapViewBundleKey";
    static final LatLng KYIV = new LatLng(50.450311, 30.523730);

    private ImageView mImageView;

    private MapView mMapView;
    // dimensions of map image
    private int mMapWidth = 600;
    private int mMapHeight = 800;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mImageView = (ImageView) findViewById(R.id.image_view);

        Bundle mapViewBundle = null;
        if (savedInstanceState != null) {
            mapViewBundle = savedInstanceState.getBundle(MAP_VIEW_BUNDLE_KEY);
        }

        GoogleMapOptions options = new GoogleMapOptions()
                .compassEnabled(false)
                .mapToolbarEnabled(false)
                .camera(CameraPosition.fromLatLngZoom(KYIV,15))
                .liteMode(true);
        mMapView = new MapView(this, options);
        mMapView.onCreate(mapViewBundle);

        mMapView.getMapAsync(new OnMapReadyCallback() {
            @Override
            public void onMapReady(GoogleMap googleMap) {

                // form your card (add markers, path etc.) here: 
                googleMap.addMarker(new MarkerOptions()
                        .position(KYIV)
                        .title("Kyiv"));

                // set map size in pixels and initiate image loading
                mMapView.measure(View.MeasureSpec.makeMeasureSpec(mMapWidth, View.MeasureSpec.EXACTLY),
                        View.MeasureSpec.makeMeasureSpec(mMapHeight, View.MeasureSpec.EXACTLY));
                mMapView.layout(0, 0, mMapWidth, mMapHeight);

                googleMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() {
                    @Override
                    public void onMapLoaded() {
                        mMapView.setDrawingCacheEnabled(true);
                        mMapView.measure(View.MeasureSpec.makeMeasureSpec(mMapWidth, View.MeasureSpec.EXACTLY),
                                View.MeasureSpec.makeMeasureSpec(mMapHeight, View.MeasureSpec.EXACTLY));
                        mMapView.layout(0, 0, mMapWidth, mMapHeight);
                        mMapView.buildDrawingCache(true);
                        Bitmap b = Bitmap.createBitmap(mMapView.getDrawingCache());
                        mMapView.setDrawingCacheEnabled(false);
                        mImageView.setImageBitmap(b);

                    }
                });

            }
        });
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        Bundle mapViewBundle = outState.getBundle(MAP_VIEW_BUNDLE_KEY);
        if (mapViewBundle == null) {
            mapViewBundle = new Bundle();
            outState.putBundle(MAP_VIEW_BUNDLE_KEY, mapViewBundle);
        }
    }
}

and activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="{PACKAGE_NAME}.MainActivity">

    <ImageView
        android:id="@+id/image_view"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        />

</RelativeLayout>

which get screenshot with marker on map:

If you wish to show the My Location dot on your lite mode map and use the default location source, you will need to call onResume() and onPause():

...
@Override
protected void onResume() {
    super.onResume();
    if (mMapView != null) {
        mMapView.onResume();
    }
}

@Override
protected void onPause() {
    if (mMapView != null) {
        mMapView.onPause();
    }
    super.onPause();
}
...

because the location source will only update between these calls.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!