Mapbox-gl-native: Snapshot with markers

Created on 2 Jun 2017  路  9Comments  路  Source: mapbox/mapbox-gl-native

Platform: Android 4.4.4
Mapbox SDK version: Mapbox 5.0.2

Snapshot #3466 taken does not contain markers that are MarkerViews and info windows above them. How can I take snapshot with markers?

Android

Most helpful comment

I used similar code

public void getScreenShotWithViews(MapboxMap.SnapshotReadyCallback snapshotReadyCallback) {
    if (mapboxMap != null) {
      mapView.setDrawingCacheEnabled(true);
      Bitmap drawingCache = mapView.getDrawingCache();
      MapboxMap.SnapshotReadyCallback cb = new MapboxMap.SnapshotReadyCallback() {
        @Override
        public void onSnapshotReady(Bitmap snapshot) {
          Bitmap bmOverlay =
              Bitmap.createBitmap(snapshot.getWidth(), snapshot.getHeight(), snapshot.getConfig());
          Canvas canvas = new Canvas(bmOverlay);
          canvas.drawBitmap(snapshot, new Matrix(), null);
          canvas.drawBitmap(drawingCache, new Matrix(), null);
          mapView.setDrawingCacheEnabled(false);
          snapshotReadyCallback.onSnapshotReady(bmOverlay);
        }
      };
      mapboxMap.snapshot(cb);
    }
  }

It works, but need to call mapView.getDrawingCache() before getting snapshot. If to call inside SnapshotReadyCallback got eglSwapBuffers error.

All 9 comments

agree same issue on android 5.1

I tried to getDrawableCache from MapView to get bitmap with markers.

  1. Clicked on map to place the marker.
  2. Bitmap created OK, but when I leave the activity #6647 eglSwapBuffers error occurs.

Occurs on Android 4.4.4, Samsung T-365, on 5.1.1 does not reproduce.

Also calling MapView.draw on new canvas causes that error.

Agree with this issue.
Very urgent task for me.
up

If this is a high requirement you can work around this issue for now by opting in to use TexureView as a rendering surface. You can use this feature through xml or MapboxMapOptions. After you need to get a reference to TextureView and execute: textureView.getBitmap();

To resolve this issue for SurfaceView we will need to draw all overlain views to a bitmap and merge that bitmap with the current snapshotted bitmap.

Been working on this, and was able to get it working with merging a bitmap of the snapshot with a bitmap of the View hierarchy. If needed, you can use the following methods to work around the issue yourself:

  public static Bitmap createBitmapFromView(@NonNull View view) {
    view.setDrawingCacheEnabled(true);
    view.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_LOW);
    view.buildDrawingCache();

    if (view.getDrawingCache() == null) {
      return null;
    }

    Bitmap snapshot = Bitmap.createBitmap(view.getDrawingCache());
    view.setDrawingCacheEnabled(false);
    view.destroyDrawingCache();
    return snapshot;
  }

  public static Bitmap mergeBitmap(@NonNull Bitmap background, @NonNull Bitmap foreground) {
    Bitmap result = Bitmap.createBitmap(background.getWidth(), background.getHeight(), background.getConfig());
    Canvas canvas = new Canvas(result);
    canvas.drawBitmap(background, 0f, 0f, null);
    canvas.drawBitmap(foreground, 10, 10, null);
    return result;
  }

What you need to do is call into createBitmapFromView with mapView and call into mergeBitmap with the bitmap from the callback and the bitmap from createBitmapFromView

device-2017-06-13-102956

PR for this in #9252

I used similar code

public void getScreenShotWithViews(MapboxMap.SnapshotReadyCallback snapshotReadyCallback) {
    if (mapboxMap != null) {
      mapView.setDrawingCacheEnabled(true);
      Bitmap drawingCache = mapView.getDrawingCache();
      MapboxMap.SnapshotReadyCallback cb = new MapboxMap.SnapshotReadyCallback() {
        @Override
        public void onSnapshotReady(Bitmap snapshot) {
          Bitmap bmOverlay =
              Bitmap.createBitmap(snapshot.getWidth(), snapshot.getHeight(), snapshot.getConfig());
          Canvas canvas = new Canvas(bmOverlay);
          canvas.drawBitmap(snapshot, new Matrix(), null);
          canvas.drawBitmap(drawingCache, new Matrix(), null);
          mapView.setDrawingCacheEnabled(false);
          snapshotReadyCallback.onSnapshotReady(bmOverlay);
        }
      };
      mapboxMap.snapshot(cb);
    }
  }

It works, but need to call mapView.getDrawingCache() before getting snapshot. If to call inside SnapshotReadyCallback got eglSwapBuffers error.

Adding this to the 5.1.0 milestone

Was this page helpful?
0 / 5 - 0 ratings