Snapshot method returns GoogleMap white image

I'm trying to get a screenshot of Google Maps V2 cards using mentioned API here , but it looks like it always returns white image of the Google logo at the bottom. If not the logo, I would be sure that it does not work, but the logo means that something is happening, and the card is simply not displayed. It's about what I'm doing:

mv.setVisibility(View.VISIBLE); mv.getMap().snapshot(new GoogleMap.SnapshotReadyCallback() { public void onSnapshotReady(Bitmap snapshot) { synchronized(finished) { finished[0] = snapshot; finished.notify(); } } }); 

I have tried several different approaches, including images drawing on another image, and various other attempts.

The only significant difference is that I use MapView, not MapFragment due to some technical problems, which I can not switch to the use of fragments.

+6
source share
4 answers

To take a picture, which you expect from a download card, take a picture.

Details: implement SnapshotReadyCallback and OnMapLoadedCallback.

 import com.google.android.gms.maps.GoogleMap.SnapshotReadyCallback; import com.google.android.gms.maps.GoogleMap.OnMapLoadedCallback; public class KmlReader extends ActionBarActivity implements SnapshotReadyCallback, OnMapLoadedCallback { 

...

  if (mMap == null) { // Try to obtain the map from the SupportMapFragment. // mMap = mMapFragment.getMap(); // // Check if we were successful in obtaining the map. // Try to obtain the map from the SupportMapFragment. mMap = ((SupportMapFragment) getSupportFragmentManager() .findFragmentById(R.id.map)).getMap(); // use the settings maptype // Check if we were successful in obtaining the map. if (mMap != null) { mMap.setOnMapLoadedCallback(this); SupportMapFragment.  if (mMap == null) { // Try to obtain the map from the SupportMapFragment. // mMap = mMapFragment.getMap(); // // Check if we were successful in obtaining the map. // Try to obtain the map from the SupportMapFragment. mMap = ((SupportMapFragment) getSupportFragmentManager() .findFragmentById(R.id.map)).getMap(); // use the settings maptype // Check if we were successful in obtaining the map. if (mMap != null) { mMap.setOnMapLoadedCallback(this); obtaining the map.  if (mMap == null) { // Try to obtain the map from the SupportMapFragment. // mMap = mMapFragment.getMap(); // // Check if we were successful in obtaining the map. // Try to obtain the map from the SupportMapFragment. mMap = ((SupportMapFragment) getSupportFragmentManager() .findFragmentById(R.id.map)).getMap(); // use the settings maptype // Check if we were successful in obtaining the map. if (mMap != null) { mMap.setOnMapLoadedCallback(this); SupportMapFragment.  if (mMap == null) { // Try to obtain the map from the SupportMapFragment. // mMap = mMapFragment.getMap(); // // Check if we were successful in obtaining the map. // Try to obtain the map from the SupportMapFragment. mMap = ((SupportMapFragment) getSupportFragmentManager() .findFragmentById(R.id.map)).getMap(); // use the settings maptype // Check if we were successful in obtaining the map. if (mMap != null) { mMap.setOnMapLoadedCallback(this); )  if (mMap == null) { // Try to obtain the map from the SupportMapFragment. // mMap = mMapFragment.getMap(); // // Check if we were successful in obtaining the map. // Try to obtain the map from the SupportMapFragment. mMap = ((SupportMapFragment) getSupportFragmentManager() .findFragmentById(R.id.map)).getMap(); // use the settings maptype // Check if we were successful in obtaining the map. if (mMap != null) { mMap.setOnMapLoadedCallback(this); );  if (mMap == null) { // Try to obtain the map from the SupportMapFragment. // mMap = mMapFragment.getMap(); // // Check if we were successful in obtaining the map. // Try to obtain the map from the SupportMapFragment. mMap = ((SupportMapFragment) getSupportFragmentManager() .findFragmentById(R.id.map)).getMap(); // use the settings maptype // Check if we were successful in obtaining the map. if (mMap != null) { mMap.setOnMapLoadedCallback(this); the map.  if (mMap == null) { // Try to obtain the map from the SupportMapFragment. // mMap = mMapFragment.getMap(); // // Check if we were successful in obtaining the map. // Try to obtain the map from the SupportMapFragment. mMap = ((SupportMapFragment) getSupportFragmentManager() .findFragmentById(R.id.map)).getMap(); // use the settings maptype // Check if we were successful in obtaining the map. if (mMap != null) { mMap.setOnMapLoadedCallback(this); 

...

 @Override public void onMapLoaded() { if (mMap != null) { mMap.snapshot(this); } } 

Do you have real bitmap when it is triggered.

 @Override public void onSnapshotReady(Bitmap bm) { if (CheckStorage.isExternalStorageWritable()) { int newHeight = 96; int newWidth = 96; int width = bm.getWidth(); int height = bm.getHeight(); float scaleWidth = ((float) newWidth) / width; float scaleHeight = ((float) newHeight) / height; // create a matrix for the manipulation Matrix matrix = new Matrix(); // resize the bit map matrix.postScale(scaleWidth, scaleHeight); // recreate the new Bitmap Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false); ) / width; @Override public void onSnapshotReady(Bitmap bm) { if (CheckStorage.isExternalStorageWritable()) { int newHeight = 96; int newWidth = 96; int width = bm.getWidth(); int height = bm.getHeight(); float scaleWidth = ((float) newWidth) / width; float scaleHeight = ((float) newHeight) / height; // create a matrix for the manipulation Matrix matrix = new Matrix(); // resize the bit map matrix.postScale(scaleWidth, scaleHeight); // recreate the new Bitmap Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false); ) / height; @Override public void onSnapshotReady(Bitmap bm) { if (CheckStorage.isExternalStorageWritable()) { int newHeight = 96; int newWidth = 96; int width = bm.getWidth(); int height = bm.getHeight(); float scaleWidth = ((float) newWidth) / width; float scaleHeight = ((float) newHeight) / height; // create a matrix for the manipulation Matrix matrix = new Matrix(); // resize the bit map matrix.postScale(scaleWidth, scaleHeight); // recreate the new Bitmap Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false); 
+7
source

This works for me. Hope this helps you:

 SnapshotReadyCallback callback = new SnapshotReadyCallback() { Bitmap bitmap; @Override public void onSnapshotReady(Bitmap snapshot) { // TODO Auto-generated method stub bitmap = snapshot; try { String mPath = Environment.getExternalStorageDirectory().toString(); FileOutputStream out = new FileOutputStream(mPath + "/ "+ nom + ".png"); bitmap.compress(Bitmap.CompressFormat.PNG, 90, out); Toast.makeText(getActivity(), "Capture OK", Toast.LENGTH_LONG).show(); } catch (Exception e) { e.printStackTrace(); Toast.makeText(getActivity(), "Capture NOT OK", Toast.LENGTH_LONG).show(); } } }; map.snapshot(callback); return true; (); SnapshotReadyCallback callback = new SnapshotReadyCallback() { Bitmap bitmap; @Override public void onSnapshotReady(Bitmap snapshot) { // TODO Auto-generated method stub bitmap = snapshot; try { String mPath = Environment.getExternalStorageDirectory().toString(); FileOutputStream out = new FileOutputStream(mPath + "/ "+ nom + ".png"); bitmap.compress(Bitmap.CompressFormat.PNG, 90, out); Toast.makeText(getActivity(), "Capture OK", Toast.LENGTH_LONG).show(); } catch (Exception e) { e.printStackTrace(); Toast.makeText(getActivity(), "Capture NOT OK", Toast.LENGTH_LONG).show(); } } }; map.snapshot(callback); return true; "/" + nom + ".png"); SnapshotReadyCallback callback = new SnapshotReadyCallback() { Bitmap bitmap; @Override public void onSnapshotReady(Bitmap snapshot) { // TODO Auto-generated method stub bitmap = snapshot; try { String mPath = Environment.getExternalStorageDirectory().toString(); FileOutputStream out = new FileOutputStream(mPath + "/ "+ nom + ".png"); bitmap.compress(Bitmap.CompressFormat.PNG, 90, out); Toast.makeText(getActivity(), "Capture OK", Toast.LENGTH_LONG).show(); } catch (Exception e) { e.printStackTrace(); Toast.makeText(getActivity(), "Capture NOT OK", Toast.LENGTH_LONG).show(); } } }; map.snapshot(callback); return true; OK", Toast.LENGTH_LONG) .show (); SnapshotReadyCallback callback = new SnapshotReadyCallback() { Bitmap bitmap; @Override public void onSnapshotReady(Bitmap snapshot) { // TODO Auto-generated method stub bitmap = snapshot; try { String mPath = Environment.getExternalStorageDirectory().toString(); FileOutputStream out = new FileOutputStream(mPath + "/ "+ nom + ".png"); bitmap.compress(Bitmap.CompressFormat.PNG, 90, out); Toast.makeText(getActivity(), "Capture OK", Toast.LENGTH_LONG).show(); } catch (Exception e) { e.printStackTrace(); Toast.makeText(getActivity(), "Capture NOT OK", Toast.LENGTH_LONG).show(); } } }; map.snapshot(callback); return true; NOT OK", Toast.LENGTH_LONG) .show (); SnapshotReadyCallback callback = new SnapshotReadyCallback() { Bitmap bitmap; @Override public void onSnapshotReady(Bitmap snapshot) { // TODO Auto-generated method stub bitmap = snapshot; try { String mPath = Environment.getExternalStorageDirectory().toString(); FileOutputStream out = new FileOutputStream(mPath + "/ "+ nom + ".png"); bitmap.compress(Bitmap.CompressFormat.PNG, 90, out); Toast.makeText(getActivity(), "Capture OK", Toast.LENGTH_LONG).show(); } catch (Exception e) { e.printStackTrace(); Toast.makeText(getActivity(), "Capture NOT OK", Toast.LENGTH_LONG).show(); } } }; map.snapshot(callback); return true; 
+3
source

I had to take a picture when the button is pressed. Therefore, in the button handler, I will put the following code:

 final SnapshotReadyCallback snapReadyCallback = new SnapshotReadyCallback() { Bitmap bitmap; @Override public void onSnapshotReady(Bitmap snapshot) { bitmap = snapshot; try { //do something with your snapshot } catch (Exception e) { e.printStackTrace(); } } }; GoogleMap.OnMapLoadedCallback mapLoadedCallback = new GoogleMap.OnMapLoadedCallback() { @Override public void onMapLoaded() { gmap.snapshot(snapReadyCallback); } }; gmap.setOnMapLoadedCallback(mapLoadedCallback); { final SnapshotReadyCallback snapReadyCallback = new SnapshotReadyCallback() { Bitmap bitmap; @Override public void onSnapshotReady(Bitmap snapshot) { bitmap = snapshot; try { //do something with your snapshot } catch (Exception e) { e.printStackTrace(); } } }; GoogleMap.OnMapLoadedCallback mapLoadedCallback = new GoogleMap.OnMapLoadedCallback() { @Override public void onMapLoaded() { gmap.snapshot(snapReadyCallback); } }; gmap.setOnMapLoadedCallback(mapLoadedCallback); 

What happens is that I call Map.setOnMapLoadedCallback (), which will wait until the map is loaded (onMapLoaded ()) and call Map.snapshot (). This ensures that the card is loaded, and you do not get a white image.

+2
source

I found that the map.snapshot () method only works under special conditions. If it is called too early, it will fail, if it is called at the end, and soon after installing the camera, it will return a snapshot of the wrong map image. I expect a snapshot to restore a snapshot map, determined last preset camera position and polylines. However, it is difficult to make the GoogleMap class wait, if he chooses the right pieces. Easy, if the user presses the button to create the snapshot because the user know when the card is ready, the more difficult, if it happens in software.

If you have CameraPosition (LatLng, zoom), it works well if MapFragment created using GoogleMapOption:

 GoogleMapOptions googleMapOptions = new GoogleMapOptions(); googleMapOptions.liteMode(true).mapType(GoogleMap.MAP_TYPE_NORMAL); // if this is what you want googleMapOptions.camera(new CameraPosition(new LatLng(56, 10), 11, 0, 0)); MapFragment.newInstance(googleMapOptions); 

If you do not have CameraPosition, it is more difficult. Perhaps you can not be CameraPosition, if it is designed so that these markers contained in the chamber, because for this calculation is required to GoogleMap been initialized width / height. (A problem with the chicken and the egg, or do it yourself).

Subclass MapFragment and overwrite onCreate

 public class FixedMapFragment extends MapFragment { public void setOncreateListener(Listener listener) { this.listener = listener; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = super.onCreateView(inflater, container, savedInstanceState); if (listener != null) { listener.onCreate(v, mMapManager); } return v; } } , savedInstanceState); public class FixedMapFragment extends MapFragment { public void setOncreateListener(Listener listener) { this.listener = listener; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = super.onCreateView(inflater, container, savedInstanceState); if (listener != null) { listener.onCreate(v, mMapManager); } return v; } } 

Then, create a snippet and set onCreateListener. onCreateListener function should update the position of the camera and set the polyline, etc.

When called onLoad on GoogleMap, we need to plan another onLoad, which takes a snapshot (or we again get the wrong tile).

 private void onLoad() { // Set camera position and polylines here mMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() { @Override public void onMapLoaded() { snapshot(mSnapshotCallback); } }); } 

Disadvantage: sometimes the card will flash "false" world map on the screen. To avoid this, we can hide the display of the map as long as the images are made using

 mapView.setVisibility(VIEW.INVISIBLE); 

It has been tested on google-maps 8.3.0 for Android.

+1
source

All Articles