[android] map snapshotter
This commit is contained in:
committed by
Ivo van Dongen
parent
a90e2f3a2c
commit
966bf8824d
@@ -0,0 +1,259 @@
|
||||
package com.mapbox.mapboxsdk.snapshotter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.UiThread;
|
||||
|
||||
import com.mapbox.mapboxsdk.R;
|
||||
import com.mapbox.mapboxsdk.camera.CameraPosition;
|
||||
import com.mapbox.mapboxsdk.constants.Style;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.storage.FileSource;
|
||||
|
||||
/**
|
||||
* The map snapshotter creates a bitmap of the map, rendered
|
||||
* off the UI thread. The snapshotter itself must be used on
|
||||
* the UI thread (for access to the main looper)
|
||||
*/
|
||||
@UiThread
|
||||
public class MapSnapshotter {
|
||||
|
||||
/**
|
||||
* Can be used to get notified of errors
|
||||
* in snapshot generation
|
||||
*
|
||||
* @see MapSnapshotter#start(MapboxMap.SnapshotReadyCallback, ErrorHandler)
|
||||
*/
|
||||
public static interface ErrorHandler {
|
||||
|
||||
/**
|
||||
* Called on error. Snapshotting will not
|
||||
* continue
|
||||
*
|
||||
* @param error the error message
|
||||
*/
|
||||
void onError(String error);
|
||||
}
|
||||
|
||||
private static final int LOGO_MARGIN_PX = 4;
|
||||
|
||||
// Holds the pointer to JNI NativeMapView
|
||||
private long nativePtr = 0;
|
||||
|
||||
private final Context context;
|
||||
private MapboxMap.SnapshotReadyCallback callback;
|
||||
private ErrorHandler errorHandler;
|
||||
|
||||
/**
|
||||
* MapSnapshotter options
|
||||
*/
|
||||
public static class Options {
|
||||
private int pixelRatio = 1;
|
||||
private int width;
|
||||
private int height;
|
||||
private String styleUrl = Style.MAPBOX_STREETS;
|
||||
private LatLngBounds region;
|
||||
private CameraPosition cameraPosition;
|
||||
|
||||
/**
|
||||
* @param width the width of the image
|
||||
* @param height the height of the image
|
||||
*/
|
||||
public Options(int width, int height) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param url The style URL to use
|
||||
* @return the mutated {@link Options}
|
||||
*/
|
||||
public Options withStyle(String url) {
|
||||
this.styleUrl = url;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param region the region to show in the snapshot.
|
||||
* This is applied after the camera position
|
||||
* @return the mutated {@link Options}
|
||||
*/
|
||||
public Options withRegion(LatLngBounds region) {
|
||||
this.region = region;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param pixelRatio the pixel ratio to use (default: 1)
|
||||
* @return the mutated {@link Options}
|
||||
*/
|
||||
public Options withPixelRatio(int pixelRatio) {
|
||||
this.pixelRatio = pixelRatio;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param cameraPosition The camera position to use,
|
||||
* the {@link CameraPosition#target} is overridden
|
||||
* by region if set in conjunction.
|
||||
* @return the mutated {@link Options}
|
||||
*/
|
||||
public Options withCameraPosition(CameraPosition cameraPosition) {
|
||||
this.cameraPosition = cameraPosition;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the width of the image
|
||||
*/
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the height of the image
|
||||
*/
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the pixel ratio
|
||||
*/
|
||||
public int getPixelRatio() {
|
||||
return pixelRatio;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the region
|
||||
*/
|
||||
@Nullable
|
||||
public LatLngBounds getRegion() {
|
||||
return region;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the style url
|
||||
*/
|
||||
public String getStyleUrl() {
|
||||
return styleUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the camera position
|
||||
*/
|
||||
@Nullable
|
||||
public CameraPosition getCameraPosition() {
|
||||
return cameraPosition;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the Map snapshotter, but doesn't start rendering or
|
||||
* loading yet.
|
||||
*
|
||||
* @param context the Context that is or contains the Application context
|
||||
* @param options the options to use for the snapshot
|
||||
*/
|
||||
public MapSnapshotter(@NonNull Context context, @NonNull Options options) {
|
||||
this.context = context.getApplicationContext();
|
||||
FileSource fileSource = FileSource.getInstance(context);
|
||||
String programCacheDir = context.getCacheDir().getAbsolutePath();
|
||||
|
||||
nativeInitialize(this, fileSource, options.pixelRatio, options.width,
|
||||
options.height, options.styleUrl, options.region, options.cameraPosition,
|
||||
programCacheDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts loading and rendering the snapshot. The callback will be fired
|
||||
* on the calling thread.
|
||||
*
|
||||
* @param callback the callback to use when the snapshot is ready
|
||||
*/
|
||||
public void start(@NonNull MapboxMap.SnapshotReadyCallback callback) {
|
||||
this.start(callback, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts loading and rendering the snapshot. The callbacks will be fired
|
||||
* on the calling thread.
|
||||
*
|
||||
* @param callback the callback to use when the snapshot is ready
|
||||
* @param errorHandler the error handler to use on snapshot errors
|
||||
*/
|
||||
public void start(@NonNull MapboxMap.SnapshotReadyCallback callback, ErrorHandler errorHandler) {
|
||||
if (this.callback != null) {
|
||||
throw new IllegalStateException("Snapshotter was already started");
|
||||
}
|
||||
|
||||
this.callback = callback;
|
||||
nativeStart();
|
||||
}
|
||||
|
||||
/**
|
||||
* Must be called in on the thread
|
||||
* the object was created on.
|
||||
*/
|
||||
public void cancel() {
|
||||
callback = null;
|
||||
nativeCancel();
|
||||
}
|
||||
|
||||
protected void addOverlay(Bitmap original) {
|
||||
float margin = context.getResources().getDisplayMetrics().density * LOGO_MARGIN_PX;
|
||||
Canvas canvas = new Canvas(original);
|
||||
Bitmap logo = BitmapFactory.decodeResource(context.getResources(), R.drawable.mapbox_logo_icon, null);
|
||||
canvas.drawBitmap(logo, margin, original.getHeight() - (logo.getHeight() + margin), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by JNI peer when snapshot is ready.
|
||||
* Always called on the origin (main) thread.
|
||||
*
|
||||
* @param bitmap the generated snapshot
|
||||
*/
|
||||
protected void onSnapshotReady(Bitmap bitmap) {
|
||||
if (callback != null) {
|
||||
addOverlay(bitmap);
|
||||
callback.onSnapshotReady(bitmap);
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by JNI peer when snapshot has failed.
|
||||
* Always called on the origin (main) thread.
|
||||
*
|
||||
* @param reason the exception string
|
||||
*/
|
||||
protected void onSnapshotFailed(String reason) {
|
||||
if (errorHandler != null) {
|
||||
errorHandler.onError(reason);
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
protected void reset() {
|
||||
callback = null;
|
||||
errorHandler = null;
|
||||
}
|
||||
|
||||
protected native void nativeInitialize(MapSnapshotter mapSnapshotter,
|
||||
FileSource fileSource, float pixelRatio,
|
||||
int width, int height, String styleUrl,
|
||||
LatLngBounds region, CameraPosition position,
|
||||
String programCacheDir);
|
||||
|
||||
protected native void nativeStart();
|
||||
|
||||
protected native void nativeCancel();
|
||||
|
||||
@Override
|
||||
protected native void finalize() throws Throwable;
|
||||
}
|
||||
Reference in New Issue
Block a user