summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvo van Dongen <info@ivovandongen.nl>2017-02-06 13:20:15 +0200
committerTobrun <tobrun.van.nuland@gmail.com>2017-02-10 21:15:18 +0100
commit2fc070ca9995bf4ceb4599ce7a94bee7a03b10b4 (patch)
tree4941842058cfddbc87b0c989d7b572ad6cc821fa
parent35b810dd6ddfc5e6f1a635b2682b3add5ec5d5bb (diff)
downloadqtlocation-mapboxgl-upstream/ivovandongen-gl-sv.tar.gz
[android] native map view refactoringupstream/ivovandongen-gl-sv
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Marker.java3
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java22
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java1055
-rw-r--r--platform/android/config.cmake28
-rw-r--r--platform/android/src/annotation/marker.cpp27
-rw-r--r--platform/android/src/annotation/marker.hpp30
-rw-r--r--platform/android/src/annotation/multi_point.hpp42
-rw-r--r--platform/android/src/annotation/polygon.cpp49
-rw-r--r--platform/android/src/annotation/polygon.hpp40
-rw-r--r--platform/android/src/annotation/polyline.cpp49
-rw-r--r--platform/android/src/annotation/polyline.hpp40
-rw-r--r--platform/android/src/conversion/collection.hpp13
-rw-r--r--platform/android/src/conversion/color.hpp24
-rw-r--r--platform/android/src/geometry/conversion/feature.hpp38
-rw-r--r--platform/android/src/geometry/feature.cpp20
-rw-r--r--platform/android/src/geometry/feature.hpp29
-rw-r--r--platform/android/src/geometry/geometry.hpp16
-rw-r--r--platform/android/src/geometry/lat_lng.cpp31
-rw-r--r--platform/android/src/geometry/lat_lng.hpp31
-rw-r--r--platform/android/src/geometry/projected_meters.cpp20
-rw-r--r--platform/android/src/geometry/projected_meters.hpp26
-rw-r--r--platform/android/src/graphics/pointf.cpp20
-rw-r--r--platform/android/src/graphics/pointf.hpp25
-rw-r--r--platform/android/src/graphics/rectf.cpp35
-rw-r--r--platform/android/src/graphics/rectf.hpp31
-rw-r--r--platform/android/src/gson/json_object.hpp16
-rw-r--r--platform/android/src/java/util.cpp18
-rw-r--r--platform/android/src/java/util.hpp33
-rwxr-xr-xplatform/android/src/jni.cpp1224
-rw-r--r--platform/android/src/jni.hpp14
-rwxr-xr-xplatform/android/src/native_map_view.cpp875
-rwxr-xr-xplatform/android/src/native_map_view.hpp186
-rw-r--r--platform/android/src/style/android_conversion.hpp1
33 files changed, 1949 insertions, 2162 deletions
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Marker.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Marker.java
index edf118205b..4d7c620435 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Marker.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Marker.java
@@ -30,6 +30,8 @@ public class Marker extends Annotation {
private LatLng position;
private String snippet;
private Icon icon;
+ //Redundantly stored for JNI access
+ private String iconId;
private String title;
private InfoWindow infoWindow;
@@ -148,6 +150,7 @@ public class Marker extends Annotation {
*/
public void setIcon(@Nullable Icon icon) {
this.icon = icon;
+ this.iconId = icon != null ? icon.getId() : null;
MapboxMap map = getMapboxMap();
if (map != null) {
map.updateMarker(this);
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java
index 11928615d6..c124531fa5 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java
@@ -149,6 +149,9 @@ public class MapView extends FrameLayout {
// Create native Map object
nativeMapView = new NativeMapView(MapView.this);
+ if (TextUtils.isEmpty(nativeMapView.getAccessToken())) {
+ nativeMapView.setAccessToken(Mapbox.getAccessToken());
+ }
//Continue configuring the map view on the main thread
MapView.this.post(new Runnable() {
@@ -173,7 +176,6 @@ public class MapView extends FrameLayout {
nativeMapView.render();
}
});
-
}
private void setupViewProperties() {
@@ -188,19 +190,6 @@ public class MapView extends FrameLayout {
requestDisallowInterceptTouchEvent(true);
}
-// private void loopRender() {
-// postDelayed(new Runnable() {
-// @Override
-// public void run() {
-// //glSurfaceView.queueEvent(renderRunnable);
-// onInvalidate();
-//// nativeMapView.update();
-// //onInvalidate();
-// loopRender();
-// }
-// }, 500);
-// }
-
protected void onNativeMapViewReady() {
// callback for focal point invalidation
@@ -336,9 +325,6 @@ public class MapView extends FrameLayout {
}
destroyed = true;
- //nativeMapView.terminateContext();
- //nativeMapView.terminateDisplay();
- //nativeMapView.destroySurface();
glSurfaceView.queueEvent(new Runnable() {
@Override
@@ -506,8 +492,6 @@ public class MapView extends FrameLayout {
if (isInEditMode()) {
return;
}
-
- //glSurfaceView.queueEvent(renderRunnable);
}
@Override
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
index 5069a25d69..f5fd886662 100755
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
@@ -8,20 +8,18 @@ import android.graphics.RectF;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
-import android.text.TextUtils;
import android.util.DisplayMetrics;
-import android.view.Surface;
-import com.mapbox.mapboxsdk.annotations.Icon;
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.Polygon;
import com.mapbox.mapboxsdk.annotations.Polyline;
-import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.geometry.ProjectedMeters;
import com.mapbox.mapboxsdk.offline.OfflineManager;
+import com.mapbox.mapboxsdk.style.layers.CannotAddLayerException;
import com.mapbox.mapboxsdk.style.layers.Layer;
import com.mapbox.mapboxsdk.style.layers.NoSuchLayerException;
+import com.mapbox.mapboxsdk.style.sources.CannotAddSourceException;
import com.mapbox.mapboxsdk.style.sources.NoSuchSourceException;
import com.mapbox.mapboxsdk.style.sources.Source;
import com.mapbox.services.commons.geojson.Feature;
@@ -37,11 +35,8 @@ import timber.log.Timber;
// Class that wraps the native methods for convenience
final class NativeMapView {
- // Flag to indicating destroy was called
- private boolean destroyed = false;
-
// Holds the pointer to JNI NativeMapView
- private long nativeMapViewPtr = 0;
+ private long nativePtr = 0;
// Used for callbacks
private MapView mapView;
@@ -50,7 +45,7 @@ final class NativeMapView {
private final float pixelRatio;
// Listeners for Map change events
- private CopyOnWriteArrayList<MapView.OnMapChangedListener> onMapChangedListeners;
+ private CopyOnWriteArrayList<MapView.OnMapChangedListener> onMapChangedListeners = new CopyOnWriteArrayList<>();
// Listener invoked to return a bitmap of the map
private MapboxMap.SnapshotReadyCallback snapshotReadyCallback;
@@ -67,23 +62,21 @@ final class NativeMapView {
// Constructors
//
- public NativeMapView(MapView mapView) {
+ NativeMapView(MapView mapView) {
this.mapView = mapView;
Context context = mapView.getContext();
- String dataPath = OfflineManager.getDatabasePath(context);
-
- // With the availability of offline, we're unifying the ambient (cache) and the offline
- // databases to be in the same folder, outside cache, to avoid automatic deletion from
- // the system
- String cachePath = dataPath;
+ String cachePath = OfflineManager.getDatabasePath(context);
pixelRatio = context.getResources().getDisplayMetrics().density;
String apkPath = context.getPackageCodePath();
+
int availableProcessors = Runtime.getRuntime().availableProcessors();
+
ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
activityManager.getMemoryInfo(memoryInfo);
+
long totalMemory = memoryInfo.availMem;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
totalMemory = memoryInfo.totalMem;
@@ -96,702 +89,389 @@ final class NativeMapView {
if (totalMemory < 0) {
throw new IllegalArgumentException("totalMemory cannot be negative.");
}
- onMapChangedListeners = new CopyOnWriteArrayList<>();
-// if (Looper.myLooper() == null) {
-// Looper.prepare();
-// }
- nativeMapViewPtr = nativeCreate(cachePath, dataPath, apkPath, pixelRatio, availableProcessors, totalMemory);
+ initialize(this, cachePath, apkPath, pixelRatio, availableProcessors, totalMemory);
}
//
// Methods
//
- public void onViewportChanged(int width, int height) {
- if (isDestroyedOn("onViewportChanged")) {
- return;
- }
+ private native void initialize(NativeMapView nativeMapView, String cachePath, String apkPath, float pixelRatio,
+ int availableProcessors, long totalMemory);
- if (width < 0) {
- throw new IllegalArgumentException("width cannot be negative.");
- }
+ native void destroy();
- if (height < 0) {
- throw new IllegalArgumentException("height cannot be negative.");
- }
+ native void render();
- if (width > 65535) {
- // we have seen edge cases where devices return incorrect values #6111
- Timber.e("Device returned an out of range width size, "
- + "capping value at 65535 instead of " + width);
- width = 65535;
- }
+ native void setStyleUrl(String url);
- if (height > 65535) {
- // we have seen edge cases where devices return incorrect values #6111
- Timber.e("Device returned an out of range height size, "
- + "capping value at 65535 instead of " + height);
- height = 65535;
- }
+ native String getStyleUrl();
- nativeOnViewportChanged(nativeMapViewPtr, width, height);
- }
+ native void setStyleJson(String styleJson);
- private boolean isDestroyedOn(String callingMethod) {
- if (destroyed && !TextUtils.isEmpty(callingMethod)) {
- Timber.e(String.format(MapboxConstants.MAPBOX_LOCALE,
- "You're calling `%s` after the `MapView` was destroyed, were you invoking it after `onDestroy()`?",
- callingMethod));
- }
- return destroyed;
- }
+ native String getStyleJson();
- public void destroy() {
- nativeDestroy(nativeMapViewPtr);
- nativeMapViewPtr = 0;
- mapView = null;
- destroyed = true;
- }
+ native void setAccessToken(String accessToken);
- public void update() {
- if (isDestroyedOn("update")) {
- return;
- }
- nativeUpdate(nativeMapViewPtr);
- }
+ native String getAccessToken();
- public void render() {
- Timber.i("Render");
- if (isDestroyedOn("render")) {
- return;
- }
- nativeRender(nativeMapViewPtr);
- }
+ native void cancelTransitions();
- public void addClass(String clazz) {
- if (isDestroyedOn("addClass")) {
- return;
- }
- nativeAddClass(nativeMapViewPtr, clazz);
- }
+ native void setGestureInProgress(boolean inProgress);
- public void removeClass(String clazz) {
- if (isDestroyedOn("removeClass")) {
- return;
- }
- nativeRemoveClass(nativeMapViewPtr, clazz);
- }
+ native void setLatLng(double latitude, double longitude);
- public boolean hasClass(String clazz) {
- if (isDestroyedOn("hasClass")) {
- return false;
- }
- return nativeHasClass(nativeMapViewPtr, clazz);
- }
+ native void resetPosition();
- public void setClasses(List<String> classes) {
- if (isDestroyedOn("setClasses")) {
- return;
- }
- nativeSetClasses(nativeMapViewPtr, classes);
- }
+ native double getPitch();
- public List<String> getClasses() {
- if (isDestroyedOn("getClasses")) {
- return new ArrayList<>();
- }
- return nativeGetClasses(nativeMapViewPtr);
- }
+ native void setPitch(double pitch);
- public void setStyleUrl(String url) {
- if (isDestroyedOn("setStyleUrl")) {
- return;
- }
- nativeSetStyleUrl(nativeMapViewPtr, url);
+ @Deprecated
+ void setPitch(double pitch, int duration) {
+ setPitch(pitch);
}
- public String getStyleUrl() {
- if (isDestroyedOn("getStyleUrl")) {
- return null;
- }
- return nativeGetStyleUrl(nativeMapViewPtr);
- }
+ native double getScale();
- public void setStyleJson(String newStyleJson) {
- if (isDestroyedOn("setStyleJson")) {
- return;
- }
- nativeSetStyleJson(nativeMapViewPtr, newStyleJson);
- }
+ native void setZoom(double zoom);
- public String getStyleJson() {
- if (isDestroyedOn("getStyleJson")) {
- return null;
- }
- return nativeGetStyleJson(nativeMapViewPtr);
- }
+ native double getZoom();
- public void setAccessToken(String accessToken) {
- if (isDestroyedOn("setAccessToken")) {
- return;
- }
- nativeSetAccessToken(nativeMapViewPtr, accessToken);
- }
+ native void resetZoom();
- public String getAccessToken() {
- if (isDestroyedOn("getAccessToken")) {
- return null;
- }
- return nativeGetAccessToken(nativeMapViewPtr);
- }
+ native void setMinZoom(double zoom);
- public void cancelTransitions() {
- if (isDestroyedOn("cancelTransitions")) {
- return;
- }
- nativeCancelTransitions(nativeMapViewPtr);
- }
+ native double getMinZoom();
- public void setGestureInProgress(boolean inProgress) {
- if (isDestroyedOn("setGestureInProgress")) {
- return;
- }
- nativeSetGestureInProgress(nativeMapViewPtr, inProgress);
- }
+ native void setMaxZoom(double zoom);
- public void moveBy(double dx, double dy) {
- if (isDestroyedOn("moveBy")) {
- return;
- }
- moveBy(dx, dy, 0);
- }
+ native double getMaxZoom();
- public void moveBy(double dx, double dy, long duration) {
- Timber.i("Move by %sx%s - %s", dx, dy, duration);
- if (isDestroyedOn("moveBy")) {
- return;
+ void onViewportChanged(int width, int height) {
+ if (width < 0) {
+ throw new IllegalArgumentException("width cannot be negative.");
}
- nativeMoveBy(nativeMapViewPtr, dx / pixelRatio, dy / pixelRatio, duration);
- }
- public void setLatLng(LatLng latLng) {
- if (isDestroyedOn("setLatLng")) {
- return;
+ if (height < 0) {
+ throw new IllegalArgumentException("height cannot be negative.");
}
- setLatLng(latLng, 0);
- }
- public void setLatLng(LatLng latLng, long duration) {
- Timber.i("setLatLng %sx%s - %s", latLng.getLatitude(), latLng.getLongitude(), duration);
- if (isDestroyedOn("setLatLng")) {
- return;
+ if (width > 65535) {
+ // we have seen edge cases where devices return incorrect values #6111
+ Timber.e("Device returned an out of range width size, "
+ + "capping value at 65535 instead of " + width);
+ width = 65535;
}
- nativeSetLatLng(nativeMapViewPtr, latLng.getLatitude(), latLng.getLongitude(), duration);
- }
- public LatLng getLatLng() {
- if (isDestroyedOn("")) {
- return new LatLng();
+ if (height > 65535) {
+ // we have seen edge cases where devices return incorrect values #6111
+ Timber.e("Device returned an out of range height size, "
+ + "capping value at 65535 instead of " + height);
+ height = 65535;
}
- // wrap longitude values coming from core
- return nativeGetLatLng(nativeMapViewPtr).wrap();
- }
- public void resetPosition() {
- if (isDestroyedOn("resetPosition")) {
- return;
- }
- nativeResetPosition(nativeMapViewPtr);
+ _onViewportChanged(width, height);
}
- public double getPitch() {
- if (isDestroyedOn("getPitch")) {
- return 0;
- }
- return nativeGetPitch(nativeMapViewPtr);
- }
+ private native void _onViewportChanged(int width, int height);
- public void setPitch(double pitch, long duration) {
- Timber.i("setLatLng %s - %s", pitch, duration);
- if (isDestroyedOn("setPitch")) {
- return;
- }
- nativeSetPitch(nativeMapViewPtr, pitch, duration);
+ void update() {
+ //TODO, this circle makes little sense atm...
+ Timber.w("TODO; Implement update()");
+ onInvalidate();
}
- public void scaleBy(double ds) {
- if (isDestroyedOn("scaleBy")) {
- return;
- }
- scaleBy(ds, Double.NaN, Double.NaN);
- }
- public void scaleBy(double ds, double cx, double cy) {
- if (isDestroyedOn("scaleBy")) {
- return;
- }
- scaleBy(ds, cx, cy, 0);
+ void moveBy(double dx, double dy) {
+ Timber.i("Move by %sx%s", dx, dy);
+ _moveBy(dx / pixelRatio, dy / pixelRatio);
}
- public void scaleBy(double ds, double cx, double cy, long duration) {
- if (isDestroyedOn("scaleBy")) {
- return;
- }
- nativeScaleBy(nativeMapViewPtr, ds, cx / pixelRatio, cy / pixelRatio, duration);
- }
+ private native void _moveBy(double dx, double dy);
- public void setScale(double scale) {
- if (isDestroyedOn("setScale")) {
- return;
- }
- setScale(scale, Double.NaN, Double.NaN);
+ @Deprecated
+ void moveBy(double dx, double dy, long duration) {
+ moveBy(dx, dy);
}
- public void setScale(double scale, double cx, double cy) {
- if (isDestroyedOn("setScale")) {
- return;
- }
- setScale(scale, cx, cy, 0);
+ void setLatLng(LatLng latLng) {
+ Timber.i("setLatLng %sx%s - %s", latLng.getLatitude(), latLng.getLongitude());
+ setLatLng(latLng.getLatitude(), latLng.getLongitude());
}
- public void setScale(double scale, double cx, double cy, long duration) {
- if (isDestroyedOn("setScale")) {
- return;
- }
- nativeSetScale(nativeMapViewPtr, scale, cx / pixelRatio, cy / pixelRatio, duration);
+ @Deprecated
+ void setLatLng(LatLng latLng, long duration) {
+ setLatLng(latLng);
}
- public double getScale() {
- if (isDestroyedOn("getScale")) {
- return 0;
- }
- return nativeGetScale(nativeMapViewPtr);
+ LatLng getLatLng() {
+ // wrap longitude values coming from core
+ return _getLatLng().wrap();
}
- public void setZoom(double zoom) {
- if (isDestroyedOn("setZoom")) {
- return;
- }
- setZoom(zoom, 0);
- }
+ private native LatLng _getLatLng();
- public void setZoom(double zoom, long duration) {
- if (isDestroyedOn("setZoom")) {
- return;
- }
- nativeSetZoom(nativeMapViewPtr, zoom, duration);
+ void scaleBy(double ds) {
+ scaleBy(ds, Double.NaN, Double.NaN);
}
- public double getZoom() {
- if (isDestroyedOn("getZoom")) {
- return 0;
- }
- return nativeGetZoom(nativeMapViewPtr);
+ void scaleBy(double ds, double cx, double cy) {
+ _scaleBy(ds, cx / pixelRatio, cy / pixelRatio);
}
- public void resetZoom() {
- if (isDestroyedOn("resetZoom")) {
- return;
- }
- nativeResetZoom(nativeMapViewPtr);
+ private native void _scaleBy(double ds, double cx, double cy);
+
+ @Deprecated
+ void scaleBy(double ds, double cx, double cy, long duration) {
+ scaleBy(ds, cx, cy);
}
- public void setMinZoom(double zoom) {
- if (isDestroyedOn("setMinZoom")) {
- return;
- }
- nativeSetMinZoom(nativeMapViewPtr, zoom);
+ void setScale(double scale) {
+ setScale(scale, Double.NaN, Double.NaN);
}
- public double getMinZoom() {
- if (isDestroyedOn("getMinZoom")) {
- return 0;
- }
- return nativeGetMinZoom(nativeMapViewPtr);
+ void setScale(double scale, double cx, double cy) {
+ _setScale(scale, cx / pixelRatio, cy / pixelRatio);
}
- public void setMaxZoom(double zoom) {
- if (isDestroyedOn("setMaxZoom")) {
- return;
- }
- nativeSetMaxZoom(nativeMapViewPtr, zoom);
+ private native void _setScale(double scale, double cx, double cy);
+
+ @Deprecated
+ void setScale(double scale, double cx, double cy, long duration) {
+ setScale(scale, cx, cy);
}
- public double getMaxZoom() {
- if (isDestroyedOn("getMaxZoom")) {
- return 0;
- }
- return nativeGetMaxZoom(nativeMapViewPtr);
+ @Deprecated
+ void setZoom(double zoom, long duration) {
+ setZoom(zoom);
}
- public void rotateBy(double sx, double sy, double ex, double ey) {
- if (isDestroyedOn("rotateBy")) {
- return;
- }
- rotateBy(sx, sy, ex, ey, 0);
+ void rotateBy(double sx, double sy, double ex, double ey) {
+ _rotateBy(sx / pixelRatio, sy / pixelRatio, ex, ey);
}
- public void rotateBy(double sx, double sy, double ex, double ey,
- long duration) {
- if (isDestroyedOn("rotateBy")) {
- return;
- }
- nativeRotateBy(nativeMapViewPtr, sx / pixelRatio, sy / pixelRatio, ex, ey, duration);
+ private native void _rotateBy(double sx, double sy, double ex, double ey);
+
+ @Deprecated
+ void rotateBy(double sx, double sy, double ex, double ey, long duration) {
+ rotateBy(sx, sy, ex, ey);
}
- public void setContentPadding(int[] padding) {
- if (isDestroyedOn("setContentPadding")) {
- return;
- }
- nativeSetContentPadding(nativeMapViewPtr,
+ void setContentPadding(int[] padding) {
+ setContentPadding(
padding[1] / pixelRatio,
padding[0] / pixelRatio,
padding[3] / pixelRatio,
padding[2] / pixelRatio);
}
- public void setBearing(double degrees) {
- if (isDestroyedOn("setBearing")) {
- return;
- }
- setBearing(degrees, 0);
- }
+ native void setContentPadding(double top, double left, double bottom, double right);
- public void setBearing(double degrees, long duration) {
- if (isDestroyedOn("setBearing")) {
- return;
- }
- nativeSetBearing(nativeMapViewPtr, degrees, duration);
+ @Deprecated
+ void setBearing(double degrees, long duration) {
+ setBearing(degrees);
}
- public void setBearing(double degrees, double cx, double cy) {
- if (isDestroyedOn("setBearing")) {
- return;
- }
- nativeSetBearingXY(nativeMapViewPtr, degrees, cx / pixelRatio, cy / pixelRatio);
- }
+ native void setBearing(double degrees);
- public void setBearing(double degrees, double fx, double fy, long duration) {
- if (isDestroyedOn("setBearing")) {
- return;
- }
- nativeSetFocalBearing(nativeMapViewPtr, degrees, fx / pixelRatio, fy / pixelRatio, duration);
+ void setBearing(double degrees, double cx, double cy) {
+ _setBearingXY(degrees, cx / pixelRatio, cy / pixelRatio);
}
- public double getBearing() {
- if (isDestroyedOn("getBearing")) {
- return 0;
- }
- return nativeGetBearing(nativeMapViewPtr);
+ @Deprecated
+ void setBearing(double degrees, double cx, double cy, long duration) {
+ setBearing(degrees, cx, cy);
}
- public void resetNorth() {
- if (isDestroyedOn("resetNorth")) {
- return;
- }
- nativeResetNorth(nativeMapViewPtr);
- }
+ private native void _setBearingXY(double degrees, double cx, double cy);
- public long addMarker(Marker marker) {
- if (isDestroyedOn("addMarker")) {
- return 0;
- }
+ native double getBearing();
+
+ native void resetNorth();
+
+ long addMarker(Marker marker) {
Marker[] markers = {marker};
- return nativeAddMarkers(nativeMapViewPtr, markers)[0];
+ return addMarkers(markers)[0];
}
- public long[] addMarkers(List<Marker> markers) {
- if (isDestroyedOn("addMarkers")) {
- return new long[] {};
- }
- return nativeAddMarkers(nativeMapViewPtr, markers.toArray(new Marker[markers.size()]));
+ long[] addMarkers(List<Marker> markers) {
+ return addMarkers(markers.toArray(new Marker[markers.size()]));
}
- public long addPolyline(Polyline polyline) {
- if (isDestroyedOn("addPolyline")) {
- return 0;
- }
+ native long[] addMarkers(Marker... markers);
+
+ long addPolyline(Polyline polyline) {
Polyline[] polylines = {polyline};
- return nativeAddPolylines(nativeMapViewPtr, polylines)[0];
+ return addPolylines(polylines)[0];
}
- public long[] addPolylines(List<Polyline> polylines) {
- if (isDestroyedOn("addPolylines")) {
- return new long[] {};
- }
- return nativeAddPolylines(nativeMapViewPtr, polylines.toArray(new Polyline[polylines.size()]));
+ long[] addPolylines(List<Polyline> polylines) {
+ return addPolylines(polylines.toArray(new Polyline[polylines.size()]));
}
- public long addPolygon(Polygon polygon) {
- if (isDestroyedOn("addPolygon")) {
- return 0;
- }
+ native long[] addPolylines(Polyline[] polylines);
+
+ long addPolygon(Polygon polygon) {
Polygon[] polygons = {polygon};
- return nativeAddPolygons(nativeMapViewPtr, polygons)[0];
+ return addPolygons(polygons)[0];
}
- public long[] addPolygons(List<Polygon> polygons) {
- if (isDestroyedOn("addPolygons")) {
- return new long[] {};
- }
- return nativeAddPolygons(nativeMapViewPtr, polygons.toArray(new Polygon[polygons.size()]));
+ long[] addPolygons(List<Polygon> polygons) {
+ return addPolygons(polygons.toArray(new Polygon[polygons.size()]));
}
- public void updateMarker(Marker marker) {
- if (isDestroyedOn("updateMarker")) {
- return;
- }
+ native long[] addPolygons(Polygon[] polygons);
+
+ void updateMarker(Marker marker) {
LatLng position = marker.getPosition();
- Icon icon = marker.getIcon();
- nativeUpdateMarker(nativeMapViewPtr, marker.getId(), position.getLatitude(), position.getLongitude(), icon.getId());
+ updateMarker(marker.getId(), position.getLatitude(), position.getLongitude(), marker.getIcon().getId());
}
- public void updatePolygon(Polygon polygon) {
- if (isDestroyedOn("updatePolygon")) {
- return;
- }
- nativeUpdatePolygon(nativeMapViewPtr, polygon.getId(), polygon);
+ private native void updateMarker(long markerId, double lat, double lon, String iconId);
+
+ void updatePolygon(Polygon polygon) {
+ updatePolygon(polygon.getId(), polygon);
}
- public void updatePolyline(Polyline polyline) {
- if (isDestroyedOn("updatePolyline")) {
- return;
- }
- nativeUpdatePolyline(nativeMapViewPtr, polyline.getId(), polyline);
+ private native void updatePolygon(long polygonId, Polygon polygon);
+
+ void updatePolyline(Polyline polyline) {
+ updatePolyline(polyline.getId(), polyline);
}
- public void removeAnnotation(long id) {
- if (isDestroyedOn("removeAnnotation")) {
- return;
- }
+ private native void updatePolyline(long polylineId, Polyline polyline);
+
+ void removeAnnotation(long id) {
long[] ids = {id};
removeAnnotations(ids);
}
- public void removeAnnotations(long[] ids) {
- if (isDestroyedOn("removeAnnotations")) {
- return;
- }
- nativeRemoveAnnotations(nativeMapViewPtr, ids);
- }
+ native void removeAnnotations(long[] id);
- public long[] queryPointAnnotations(RectF rect) {
- if (isDestroyedOn("queryPointAnnotations")) {
- return new long[] {};
- }
- return nativeQueryPointAnnotations(nativeMapViewPtr, rect);
- }
+ native long[] queryPointAnnotations(RectF rect);
- public void addAnnotationIcon(String symbol, int width, int height, float scale, byte[] pixels) {
- if (isDestroyedOn("addAnnotationIcon")) {
- return;
- }
- nativeAddAnnotationIcon(nativeMapViewPtr, symbol, width, height, scale, pixels);
- }
+ native void addAnnotationIcon(String symbol, int width, int height, float scale, byte[] pixels);
- public void setVisibleCoordinateBounds(LatLng[] coordinates, RectF padding, double direction, long duration) {
- if (isDestroyedOn("setVisibleCoordinateBounds")) {
- return;
- }
- nativeSetVisibleCoordinateBounds(nativeMapViewPtr, coordinates, padding, direction, duration);
+ @Deprecated
+ void setVisibleCoordinateBounds(LatLng[] coordinates, RectF padding, double direction, long duration) {
+ setVisibleCoordinateBounds(coordinates, padding, direction);
}
- public void onLowMemory() {
- if (isDestroyedOn("onLowMemory")) {
- return;
- }
- nativeOnLowMemory(nativeMapViewPtr);
- }
+ native void setVisibleCoordinateBounds(LatLng[] coordinates, RectF padding, double direction);
- public void setDebug(boolean debug) {
- if (isDestroyedOn("setDebug")) {
- return;
- }
- nativeSetDebug(nativeMapViewPtr, debug);
- }
+ native void onLowMemory();
- public void cycleDebugOptions() {
- if (isDestroyedOn("cycleDebugOptions")) {
- return;
- }
- nativeToggleDebug(nativeMapViewPtr);
- }
+ native void setDebug(boolean debug);
- public boolean getDebug() {
- if (isDestroyedOn("getDebug")) {
- return false;
- }
- return nativeGetDebug(nativeMapViewPtr);
- }
+ native void cycleDebugOptions();
- public boolean isFullyLoaded() {
- if (isDestroyedOn("isFullyLoaded")) {
- return false;
- }
- return nativeIsFullyLoaded(nativeMapViewPtr);
- }
+ native boolean getDebug();
- public void setReachability(boolean status) {
- if (isDestroyedOn("setReachability")) {
- return;
- }
- nativeSetReachability(nativeMapViewPtr, status);
+ native boolean isFullyLoaded();
+
+ double getMetersPerPixelAtLatitude(double lat) {
+ return getMetersPerPixelAtLatitude(lat, getZoom());
}
- public double getMetersPerPixelAtLatitude(double lat) {
- if (isDestroyedOn("getMetersPerPixelAtLatitude")) {
- return 0;
- }
- return nativeGetMetersPerPixelAtLatitude(nativeMapViewPtr, lat, getZoom());
+ private native double getMetersPerPixelAtLatitude(double lat, double zoom);
+
+ ProjectedMeters projectedMetersForLatLng(LatLng latLng) {
+ return projectedMetersForLatLng(latLng.getLatitude(), latLng.getLongitude());
}
- public ProjectedMeters projectedMetersForLatLng(LatLng latLng) {
- if (isDestroyedOn("projectedMetersForLatLng")) {
- return null;
- }
- return nativeProjectedMetersForLatLng(nativeMapViewPtr, latLng.getLatitude(), latLng.getLongitude());
+ native ProjectedMeters projectedMetersForLatLng(double latitude, double longitude);
+
+ LatLng latLngForProjectedMeters(ProjectedMeters projectedMeters) {
+ return latLngForProjectedMeters(projectedMeters.getNorthing(), projectedMeters.getEasting()).wrap();
}
- public LatLng latLngForProjectedMeters(ProjectedMeters projectedMeters) {
- if (isDestroyedOn("latLngForProjectedMeters")) {
- return new LatLng();
- }
- return nativeLatLngForProjectedMeters(nativeMapViewPtr, projectedMeters.getNorthing(),
- projectedMeters.getEasting()).wrap();
+ private native LatLng latLngForProjectedMeters(double northing, double easting);
+
+ LatLng latLngForPixel(PointF pixel) {
+ return latLngForPixel(pixel.x / pixelRatio, pixel.y / pixelRatio).wrap();
}
- public PointF pixelForLatLng(LatLng latLng) {
- if (isDestroyedOn("pixelForLatLng")) {
- return new PointF();
- }
- PointF pointF = nativePixelForLatLng(nativeMapViewPtr, latLng.getLatitude(), latLng.getLongitude());
+ private native LatLng latLngForPixel(float x, float y);
+
+ PointF pixelForLatLng(LatLng latLng) {
+ PointF pointF = pixelForLatLng(latLng.getLatitude(), latLng.getLongitude());
pointF.set(pointF.x * pixelRatio, pointF.y * pixelRatio);
return pointF;
}
- public LatLng latLngForPixel(PointF pixel) {
- if (isDestroyedOn("latLngForPixel")) {
- return new LatLng();
- }
- return nativeLatLngForPixel(nativeMapViewPtr, pixel.x / pixelRatio, pixel.y / pixelRatio).wrap();
- }
+ private native PointF pixelForLatLng(double lat, double lon);
- public double getTopOffsetPixelsForAnnotationSymbol(String symbolName) {
- if (isDestroyedOn("getTopOffsetPixelsForAnnotationSymbol")) {
- return 0;
- }
- return nativeGetTopOffsetPixelsForAnnotationSymbol(nativeMapViewPtr, symbolName);
- }
+ native double getTopOffsetPixelsForAnnotationSymbol(String symbolName);
- public void jumpTo(double angle, LatLng center, double pitch, double zoom) {
- if (isDestroyedOn("jumpTo")) {
- return;
- }
- nativeJumpTo(nativeMapViewPtr, angle, center.getLatitude(), center.getLongitude(), pitch, zoom);
+ @Deprecated
+ void jumpTo(double angle, LatLng center, double pitch, double zoom) {
+ Timber.w("Deprecated");
}
- public void easeTo(double angle, LatLng center, long duration, double pitch, double zoom,
- boolean easingInterpolator) {
- if (isDestroyedOn("easeTo")) {
- return;
- }
- nativeEaseTo(nativeMapViewPtr, angle, center.getLatitude(), center.getLongitude(), duration, pitch, zoom,
- easingInterpolator);
+ @Deprecated
+ void easeTo(double angle, LatLng center, long duration, double pitch, double zoom,
+ boolean easingInterpolator) {
+ Timber.w("Deprecated");
}
- public void flyTo(double angle, LatLng center, long duration, double pitch, double zoom) {
- if (isDestroyedOn("flyTo")) {
- return;
- }
- nativeFlyTo(nativeMapViewPtr, angle, center.getLatitude(), center.getLongitude(), duration, pitch, zoom);
- }
-
- public double[] getCameraValues() {
- if (isDestroyedOn("getCameraValues")) {
- return new double[] {};
- }
- return nativeGetCameraValues(nativeMapViewPtr);
+ @Deprecated
+ void flyTo(double angle, LatLng center, long duration, double pitch, double zoom) {
+ Timber.w("Deprecated");
}
// Runtime style Api
- public long getTransitionDuration() {
- return nativeGetTransitionDuration(nativeMapViewPtr);
- }
+ native long getTransitionDuration();
- public void setTransitionDuration(long duration) {
- nativeSetTransitionDuration(nativeMapViewPtr, duration);
- }
+ native void setTransitionDuration(long duration);
- public long getTransitionDelay() {
- return nativeGetTransitionDelay(nativeMapViewPtr);
- }
+ native long getTransitionDelay();
- public void setTransitionDelay(long delay) {
- nativeSetTransitionDelay(nativeMapViewPtr, delay);
- }
+ native void setTransitionDelay(long delay);
- public Layer getLayer(String layerId) {
- if (isDestroyedOn("getLayer")) {
- return null;
- }
- return nativeGetLayer(nativeMapViewPtr, layerId);
- }
+ native Layer getLayer(String layerId);
- public void addLayer(@NonNull Layer layer, @Nullable String before) {
- if (isDestroyedOn("")) {
- return;
- }
- nativeAddLayer(nativeMapViewPtr, layer.getNativePtr(), before);
+ void addLayer(@NonNull Layer layer, @Nullable String before) throws CannotAddLayerException {
+ addLayer(layer.getNativePtr(), before);
}
- public void removeLayer(@NonNull String layerId) throws NoSuchLayerException {
- if (isDestroyedOn("removeLayer")) {
- return;
- }
- nativeRemoveLayerById(nativeMapViewPtr, layerId);
- }
+ private native void addLayer(long layerPtr, String before) throws CannotAddLayerException;
- public void removeLayer(@NonNull Layer layer) throws NoSuchLayerException {
- if (isDestroyedOn("removeLayer")) {
- return;
- }
- nativeRemoveLayer(nativeMapViewPtr, layer.getNativePtr());
+ void removeLayer(@NonNull String layerId) throws NoSuchLayerException {
+ removeLayerById(layerId);
}
- public Source getSource(@NonNull String sourceId) {
- if (isDestroyedOn("getSource")) {
- return null;
- }
- return nativeGetSource(nativeMapViewPtr, sourceId);
+ private native void removeLayerById(String layerId) throws NoSuchLayerException;
+
+ void removeLayer(@NonNull Layer layer) throws NoSuchLayerException {
+ removeLayer(layer.getNativePtr());
}
- public void addSource(@NonNull Source source) {
- if (isDestroyedOn("addSource")) {
- return;
- }
- nativeAddSource(nativeMapViewPtr, source.getNativePtr());
+ private native void removeLayer(long layerId) throws NoSuchLayerException;
+
+ native Source getSource(String sourceId);
+
+ void addSource(@NonNull Source source) throws CannotAddSourceException {
+ addSource(source.getNativePtr());
}
- public void removeSource(@NonNull String sourceId) throws NoSuchSourceException {
- if (isDestroyedOn("removeSource")) {
- return;
- }
- nativeRemoveSourceById(nativeMapViewPtr, sourceId);
+ private native void addSource(long nativeSourcePtr) throws CannotAddSourceException;
+
+ void removeSource(@NonNull String sourceId) throws NoSuchSourceException {
+ removeSourceById(sourceId);
}
- public void removeSource(@NonNull Source source) throws NoSuchSourceException {
- if (isDestroyedOn("removeSource")) {
- return;
- }
- nativeRemoveSource(nativeMapViewPtr, source.getNativePtr());
+ private native void removeSourceById(String sourceId) throws NoSuchSourceException;
+
+ void removeSource(@NonNull Source source) throws NoSuchSourceException {
+ removeSource(source.getNativePtr());
}
- public void addImage(@NonNull String name, @NonNull Bitmap image) {
- if (isDestroyedOn("addImage")) {
- return;
- }
+ private native void removeSource(long sourcePtr) throws NoSuchSourceException;
+
+ void addImage(@NonNull String name, @NonNull Bitmap image) {
// Check/correct config
if (image.getConfig() != Bitmap.Config.ARGB_8888) {
image = image.copy(Bitmap.Config.ARGB_8888, false);
@@ -805,35 +485,27 @@ final class NativeMapView {
float density = image.getDensity() == Bitmap.DENSITY_NONE ? Bitmap.DENSITY_NONE : image.getDensity();
float pixelRatio = density / DisplayMetrics.DENSITY_DEFAULT;
- nativeAddImage(nativeMapViewPtr, name, image.getWidth(), image.getHeight(), pixelRatio, buffer.array());
+ addImage(name, image.getWidth(), image.getHeight(), pixelRatio, buffer.array());
}
- public void removeImage(String name) {
- if (isDestroyedOn("removeImage")) {
- return;
- }
- nativeRemoveImage(nativeMapViewPtr, name);
- }
+ private native void addImage(String name, int width, int height, float pixelRatio, byte[] array);
+
+ native void removeImage(String name);
- // Feature querying
+ // Feature querying //
@NonNull
- public List<Feature> queryRenderedFeatures(PointF coordinates, String... layerIds) {
- if (isDestroyedOn("queryRenderedFeatures")) {
- return new ArrayList<>();
- }
- Feature[] features = nativeQueryRenderedFeaturesForPoint(nativeMapViewPtr, coordinates.x / pixelRatio,
+ List<Feature> queryRenderedFeatures(PointF coordinates, String... layerIds) {
+ Feature[] features = queryRenderedFeaturesForPoint(coordinates.x / pixelRatio,
coordinates.y / pixelRatio, layerIds);
return features != null ? Arrays.asList(features) : new ArrayList<Feature>();
}
+ private native Feature[] queryRenderedFeaturesForPoint(float x, float y, String[] layerIds);
+
@NonNull
- public List<Feature> queryRenderedFeatures(RectF coordinates, String... layerIds) {
- if (isDestroyedOn("queryRenderedFeatures")) {
- return new ArrayList<>();
- }
- Feature[] features = nativeQueryRenderedFeaturesForBox(
- nativeMapViewPtr,
+ List<Feature> queryRenderedFeatures(RectF coordinates, String... layerIds) {
+ Feature[] features = queryRenderedFeaturesForBox(
coordinates.left / pixelRatio,
coordinates.top / pixelRatio,
coordinates.right / pixelRatio,
@@ -842,25 +514,14 @@ final class NativeMapView {
return features != null ? Arrays.asList(features) : new ArrayList<Feature>();
}
- public void scheduleTakeSnapshot() {
- if (isDestroyedOn("scheduleTakeSnapshot")) {
- return;
- }
- nativeScheduleTakeSnapshot(nativeMapViewPtr);
- }
-
- public void setApiBaseUrl(String baseUrl) {
- if (isDestroyedOn("setApiBaseUrl")) {
- return;
- }
- nativeSetAPIBaseURL(nativeMapViewPtr, baseUrl);
- }
+ private native Feature[] queryRenderedFeaturesForBox(float left, float top, float right,
+ float bottom, String[] layerIds);
- public float getPixelRatio() {
+ float getPixelRatio() {
return pixelRatio;
}
- public Context getContext() {
+ Context getContext() {
return mapView.getContext();
}
@@ -876,11 +537,19 @@ final class NativeMapView {
mapView.onInvalidate();
}
- protected void wakeCallback() {
+ /**
+ * Called through JNI when the render thread needs to be woken up
+ */
+ protected void onWake() {
Timber.i("wake!");
mapView.requestRender();
}
+ /**
+ * Called through JNI when the map state changed
+ *
+ * @param rawChange the mbgl::MapChange as an int
+ */
protected void onMapChanged(final int rawChange) {
Timber.i("onMapChanged: %s", rawChange);
if (onMapChangedListeners != null) {
@@ -895,235 +564,41 @@ final class NativeMapView {
}
}
+ /**
+ * Called through JNI if fps is enabled and the fps changed
+ *
+ * @param fps the Frames Per Second
+ */
protected void onFpsChanged(double fps) {
mapView.onFpsChanged(fps);
}
+ /**
+ * Called through JNI when a requested snapshot is ready
+ *
+ * @param bitmap the snapshot as a bitmap
+ */
protected void onSnapshotReady(Bitmap bitmap) {
if (snapshotReadyCallback != null && bitmap != null) {
snapshotReadyCallback.onSnapshotReady(bitmap);
}
}
- //
- // JNI methods
- //
-
- private native long nativeCreate(String cachePath, String dataPath, String apkPath, float pixelRatio,
- int availableProcessors, long totalMemory);
-
- private native void nativeDestroy(long nativeMapViewPtr);
-
- private native void nativeInitializeDisplay(long nativeMapViewPtr);
-
- private native void nativeTerminateDisplay(long nativeMapViewPtr);
-
- private native void nativeInitializeContext(long nativeMapViewPtr);
-
- private native void nativeTerminateContext(long nativeMapViewPtr);
-
- private native void nativeCreateSurface(long nativeMapViewPtr,
- Surface surface);
-
- private native void nativeDestroySurface(long nativeMapViewPtr);
-
- private native void nativeUpdate(long nativeMapViewPtr);
-
- private native void nativeRender(long nativeMapViewPtr);
-
- private native void nativeOnViewportChanged(long nativeMapViewPtr, int width, int height);
-
- private native void nativeAddClass(long nativeMapViewPtr, String clazz);
-
- private native void nativeRemoveClass(long nativeMapViewPtr, String clazz);
+ native void setReachability(boolean status);
- private native boolean nativeHasClass(long nativeMapViewPtr, String clazz);
+ native double[] getCameraValues();
- private native void nativeSetClasses(long nativeMapViewPtr,
- List<String> classes);
+ native void scheduleSnapshot();
- private native List<String> nativeGetClasses(long nativeMapViewPtr);
+ native void setApiBaseUrl(String baseUrl);
- private native void nativeSetStyleUrl(long nativeMapViewPtr, String url);
-
- private native String nativeGetStyleUrl(long nativeMapViewPtr);
-
- private native void nativeSetStyleJson(long nativeMapViewPtr, String newStyleJson);
-
- private native String nativeGetStyleJson(long nativeMapViewPtr);
-
- private native void nativeSetAccessToken(long nativeMapViewPtr, String accessToken);
-
- private native String nativeGetAccessToken(long nativeMapViewPtr);
-
- private native void nativeCancelTransitions(long nativeMapViewPtr);
-
- private native void nativeSetGestureInProgress(long nativeMapViewPtr, boolean inProgress);
-
- private native void nativeMoveBy(long nativeMapViewPtr, double dx,
- double dy, long duration);
-
- private native void nativeSetLatLng(long nativeMapViewPtr, double latitude, double longitude,
- long duration);
-
- private native LatLng nativeGetLatLng(long nativeMapViewPtr);
-
- private native void nativeResetPosition(long nativeMapViewPtr);
-
- private native double nativeGetPitch(long nativeMapViewPtr);
-
- private native void nativeSetPitch(long nativeMapViewPtr, double pitch, long duration);
-
- private native void nativeScaleBy(long nativeMapViewPtr, double ds,
- double cx, double cy, long duration);
-
- private native void nativeSetScale(long nativeMapViewPtr, double scale,
- double cx, double cy, long duration);
-
- private native double nativeGetScale(long nativeMapViewPtr);
-
- private native void nativeSetZoom(long nativeMapViewPtr, double zoom,
- long duration);
-
- private native double nativeGetZoom(long nativeMapViewPtr);
-
- private native void nativeResetZoom(long nativeMapViewPtr);
-
- private native void nativeSetMinZoom(long nativeMapViewPtr, double zoom);
-
- private native double nativeGetMinZoom(long nativeMapViewPtr);
-
- private native void nativeSetMaxZoom(long nativeMapViewPtr, double zoom);
-
- private native double nativeGetMaxZoom(long nativeMapViewPtr);
-
- private native void nativeRotateBy(long nativeMapViewPtr, double sx,
- double sy, double ex, double ey, long duration);
-
- private native void nativeSetContentPadding(long nativeMapViewPtr, double top, double left, double bottom,
- double right);
-
- private native void nativeSetBearing(long nativeMapViewPtr, double degrees,
- long duration);
-
- private native void nativeSetBearingXY(long nativeMapViewPtr, double degrees,
- double cx, double cy);
-
- private native void nativeSetFocalBearing(long nativeMapViewPtr, double degrees,
- double fx, double fy, long duration);
-
- private native double nativeGetBearing(long nativeMapViewPtr);
-
- private native void nativeResetNorth(long nativeMapViewPtr);
-
- private native void nativeUpdateMarker(long nativeMapViewPtr, long markerId, double lat, double lon, String iconId);
-
- private native long[] nativeAddMarkers(long nativeMapViewPtr, Marker[] markers);
-
- private native long[] nativeAddPolylines(long nativeMapViewPtr, Polyline[] polylines);
-
- private native long[] nativeAddPolygons(long nativeMapViewPtr, Polygon[] polygons);
-
- private native void nativeRemoveAnnotations(long nativeMapViewPtr, long[] id);
-
- private native long[] nativeQueryPointAnnotations(long nativeMapViewPtr, RectF rect);
-
- private native void nativeAddAnnotationIcon(long nativeMapViewPtr, String symbol,
- int width, int height, float scale, byte[] pixels);
-
- private native void nativeSetVisibleCoordinateBounds(long nativeMapViewPtr, LatLng[] coordinates,
- RectF padding, double direction, long duration);
-
- private native void nativeOnLowMemory(long nativeMapViewPtr);
-
- private native void nativeSetDebug(long nativeMapViewPtr, boolean debug);
-
- private native void nativeToggleDebug(long nativeMapViewPtr);
-
- private native boolean nativeGetDebug(long nativeMapViewPtr);
-
- private native boolean nativeIsFullyLoaded(long nativeMapViewPtr);
-
- private native void nativeSetReachability(long nativeMapViewPtr, boolean status);
-
- private native double nativeGetMetersPerPixelAtLatitude(long nativeMapViewPtr, double lat, double zoom);
-
- private native ProjectedMeters nativeProjectedMetersForLatLng(long nativeMapViewPtr, double latitude,
- double longitude);
-
- private native LatLng nativeLatLngForProjectedMeters(long nativeMapViewPtr, double northing, double easting);
-
- private native PointF nativePixelForLatLng(long nativeMapViewPtr, double lat, double lon);
-
- private native LatLng nativeLatLngForPixel(long nativeMapViewPtr, float x, float y);
-
- private native double nativeGetTopOffsetPixelsForAnnotationSymbol(long nativeMapViewPtr, String symbolName);
-
- private native void nativeJumpTo(long nativeMapViewPtr, double angle, double latitude, double longitude,
- double pitch, double zoom);
-
- private native void nativeEaseTo(long nativeMapViewPtr, double angle, double latitude, double longitude,
- long duration, double pitch, double zoom, boolean easingInterpolator);
-
- private native void nativeFlyTo(long nativeMapViewPtr, double angle, double latitude, double longitude,
- long duration, double pitch, double zoom);
-
- private native double[] nativeGetCameraValues(long nativeMapViewPtr);
-
- private native long nativeGetTransitionDuration(long nativeMapViewPtr);
-
- private native void nativeSetTransitionDuration(long nativeMapViewPtr, long duration);
-
- private native long nativeGetTransitionDelay(long nativeMapViewPtr);
-
- private native void nativeSetTransitionDelay(long nativeMapViewPtr, long delay);
-
- private native Layer nativeGetLayer(long nativeMapViewPtr, String layerId);
-
- private native void nativeAddLayer(long nativeMapViewPtr, long layerPtr, String before);
-
- private native void nativeRemoveLayerById(long nativeMapViewPtr, String layerId) throws NoSuchLayerException;
-
- private native void nativeRemoveLayer(long nativeMapViewPtr, long layerId) throws NoSuchLayerException;
-
- private native Source nativeGetSource(long nativeMapViewPtr, String sourceId);
-
- private native void nativeAddSource(long nativeMapViewPtr, long nativeSourcePtr);
-
- private native void nativeRemoveSourceById(long nativeMapViewPtr, String sourceId) throws NoSuchSourceException;
-
- private native void nativeRemoveSource(long nativeMapViewPtr, long sourcePtr) throws NoSuchSourceException;
-
- private native void nativeAddImage(long nativeMapViewPtr, String name, int width, int height, float pixelRatio,
- byte[] array);
-
- private native void nativeRemoveImage(long nativeMapViewPtr, String name);
-
- private native void nativeUpdatePolygon(long nativeMapViewPtr, long polygonId, Polygon polygon);
-
- private native void nativeUpdatePolyline(long nativeMapviewPtr, long polylineId, Polyline polyline);
-
- private native void nativeScheduleTakeSnapshot(long nativeMapViewPtr);
-
- private native Feature[] nativeQueryRenderedFeaturesForPoint(long nativeMapViewPtr, float x, float y, String[]
- layerIds);
-
- private native Feature[] nativeQueryRenderedFeaturesForBox(long nativeMapViewPtr, float left, float top, float right,
- float bottom, String[] layerIds);
-
- private native void nativeSetAPIBaseURL(long nativeMapViewPtr, String baseUrl);
+ native void enableFps(boolean enable);
int getWidth() {
- if (isDestroyedOn("")) {
- return 0;
- }
return mapView.getWidth();
}
int getHeight() {
- if (isDestroyedOn("")) {
- return 0;
- }
return mapView.getHeight();
}
@@ -1145,7 +620,7 @@ final class NativeMapView {
void addSnapshotCallback(@NonNull MapboxMap.SnapshotReadyCallback callback) {
snapshotReadyCallback = callback;
- scheduleTakeSnapshot();
+ scheduleSnapshot();
render();
}
}
diff --git a/platform/android/config.cmake b/platform/android/config.cmake
index 9491071f2a..c24b816c04 100644
--- a/platform/android/config.cmake
+++ b/platform/android/config.cmake
@@ -15,7 +15,7 @@ if ((ANDROID_ABI STREQUAL "armeabi") OR (ANDROID_ABI STREQUAL "armeabi-v7a") OR
set(CMAKE_SHARED_LINKER_FLAGS "-fuse-ld=gold -Wl,--icf=safe ${CMAKE_SHARED_LINKER_FLAGS}")
endif()
-mason_use(jni.hpp VERSION 2.0.0-1 HEADER_ONLY)
+mason_use(jni.hpp VERSION 3.0.0 HEADER_ONLY)
mason_use(libzip VERSION 1.1.3)
mason_use(nunicode VERSION 1.7.1)
mason_use(sqlite VERSION 3.14.2)
@@ -137,6 +137,32 @@ macro(mbgl_platform_core)
platform/android/src/native_map_view.cpp
platform/android/src/native_map_view.hpp
+ # Java core classes
+ platform/android/src/java/util.cpp
+ platform/android/src/java/util.hpp
+
+ # Graphics
+ platform/android/src/graphics/pointf.cpp
+ platform/android/src/graphics/pointf.hpp
+ platform/android/src/graphics/rectf.cpp
+ platform/android/src/graphics/rectf.hpp
+
+ # Geometry
+ platform/android/src/geometry/feature.cpp
+ platform/android/src/geometry/feature.hpp
+ platform/android/src/geometry/lat_lng.cpp
+ platform/android/src/geometry/lat_lng.hpp
+ platform/android/src/geometry/projected_meters.cpp
+ platform/android/src/geometry/projected_meters.hpp
+
+ # Annotation
+ platform/android/src/annotation/marker.cpp
+ platform/android/src/annotation/marker.hpp
+ platform/android/src/annotation/polygon.cpp
+ platform/android/src/annotation/polygon.hpp
+ platform/android/src/annotation/polyline.cpp
+ platform/android/src/annotation/polyline.hpp
+
# Main jni bindings
platform/android/src/attach_env.cpp
platform/android/src/attach_env.hpp
diff --git a/platform/android/src/annotation/marker.cpp b/platform/android/src/annotation/marker.cpp
new file mode 100644
index 0000000000..fa709fd1c9
--- /dev/null
+++ b/platform/android/src/annotation/marker.cpp
@@ -0,0 +1,27 @@
+#include "marker.hpp"
+
+namespace mbgl {
+namespace android {
+
+jni::Class<Marker> Marker::javaClass;
+
+mbgl::Point<double> Marker::getPosition(jni::JNIEnv& env, jni::Object<Marker> marker) {
+ static auto positionField = Marker::javaClass.GetField<jni::Object<LatLng>>(env, "position");
+ auto position = marker.Get(env, positionField);
+ return LatLng::getGeometry(env, position);
+}
+
+std::string Marker::getIconId(jni::JNIEnv& env, jni::Object<Marker> marker) {
+ static auto iconIdField = Marker::javaClass.GetField<jni::String>(env, "iconId");
+ auto jIconId = marker.Get(env, iconIdField);
+ return jni::Make<std::string>(env, jIconId);
+}
+
+void Marker::registerNative(jni::JNIEnv& env) {
+ // Lookup the class
+ Marker::javaClass = *jni::Class<Marker>::Find(env).NewGlobalRef(env).release();
+}
+
+
+} // namespace android
+} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/annotation/marker.hpp b/platform/android/src/annotation/marker.hpp
new file mode 100644
index 0000000000..b11a225245
--- /dev/null
+++ b/platform/android/src/annotation/marker.hpp
@@ -0,0 +1,30 @@
+#pragma once
+
+#include <mbgl/util/noncopyable.hpp>
+#include <jni/jni.hpp>
+
+#include <string>
+
+#include "../geometry/lat_lng.hpp"
+
+namespace mbgl {
+namespace android {
+
+class Marker : private mbgl::util::noncopyable {
+public:
+
+ static constexpr auto Name() { return "com/mapbox/mapboxsdk/annotations/Marker"; };
+
+ static jni::Class<Marker> javaClass;
+
+ static mbgl::Point<double> getPosition(jni::JNIEnv&, jni::Object<Marker>);
+
+ static std::string getIconId(jni::JNIEnv&, jni::Object<Marker>);
+
+ static void registerNative(jni::JNIEnv&);
+
+};
+
+
+} // namespace android
+} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/annotation/multi_point.hpp b/platform/android/src/annotation/multi_point.hpp
new file mode 100644
index 0000000000..e1152dfd60
--- /dev/null
+++ b/platform/android/src/annotation/multi_point.hpp
@@ -0,0 +1,42 @@
+#pragma once
+
+#include <mbgl/util/noncopyable.hpp>
+#include <jni/jni.hpp>
+
+#include "../geometry/lat_lng.hpp"
+#include "../java/util.hpp"
+
+namespace mbgl {
+namespace android {
+
+class MultiPoint : protected mbgl::util::noncopyable {
+
+protected:
+
+ template <class Geometry>
+ static Geometry toGeometry(JNIEnv& env, jni::Object<java::util::List> pointsList) {
+ NullCheck(env, &pointsList);
+ auto jarray = java::util::List::toArray<LatLng>(env, pointsList);
+ NullCheck(env, &jarray);
+
+ std::size_t size = jarray.Length(env);
+
+ Geometry geometry;
+ geometry.reserve(size);
+
+ for (std::size_t i = 0; i < size; i++) {
+ auto latLng = jarray.Get(env, i);
+ NullCheck(env, &latLng);
+
+ geometry.push_back(LatLng::getGeometry(env, latLng));
+
+ jni::DeleteLocalRef(env, latLng);
+ }
+
+ jni::DeleteLocalRef(env, jarray);
+ return geometry;
+ }
+};
+
+} // namespace android
+} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/annotation/polygon.cpp b/platform/android/src/annotation/polygon.cpp
new file mode 100644
index 0000000000..b0419628b0
--- /dev/null
+++ b/platform/android/src/annotation/polygon.cpp
@@ -0,0 +1,49 @@
+#include "polygon.hpp"
+
+#include "../conversion/color.hpp"
+
+namespace mbgl {
+namespace android {
+
+jni::Class<Polygon> Polygon::javaClass;
+
+mbgl::FillAnnotation Polygon::toAnnotation(jni::JNIEnv& env, jni::Object<Polygon> polygon) {
+ auto points = Polygon::getPoints(env, polygon);
+
+ mbgl::FillAnnotation annotation { mbgl::Polygon<double> { MultiPoint::toGeometry<mbgl::LinearRing<double>>(env, points) } };
+ annotation.opacity = { Polygon::getOpacity(env, polygon) };
+ annotation.color = { Polygon::getFillColor(env, polygon) };
+ annotation.outlineColor = { Polygon::getOutlineColor(env, polygon) };
+
+ jni::DeleteLocalRef(env, points);
+
+ return annotation;
+}
+
+jni::Object<java::util::List> Polygon::getPoints(jni::JNIEnv& env, jni::Object<Polygon> polygon) {
+ static auto field = Polygon::javaClass.GetField<jni::Object<java::util::List>>(env, "points");
+ return polygon.Get(env, field);
+}
+
+float Polygon::getOpacity(jni::JNIEnv& env, jni::Object<Polygon> polygon) {
+ static auto field = Polygon::javaClass.GetField<float>(env, "alpha");
+ return polygon.Get(env, field);
+}
+
+mbgl::Color Polygon::getFillColor(jni::JNIEnv& env, jni::Object<Polygon> polygon) {
+ static auto field = Polygon::javaClass.GetField<int>(env, "fillColor");
+ return *conversion::convert<mbgl::Color, int>(env, polygon.Get(env, field));
+}
+
+mbgl::Color Polygon::getOutlineColor(jni::JNIEnv& env, jni::Object<Polygon> polygon) {
+ static auto field = Polygon::javaClass.GetField<float>(env, "strokeColor");
+ return *conversion::convert<mbgl::Color, int>(env, polygon.Get(env, field));
+}
+
+void Polygon::registerNative(jni::JNIEnv& env) {
+ Polygon::javaClass = *jni::Class<Polygon>::Find(env).NewGlobalRef(env).release();
+}
+
+
+} // namespace android
+} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/annotation/polygon.hpp b/platform/android/src/annotation/polygon.hpp
new file mode 100644
index 0000000000..658aa5344b
--- /dev/null
+++ b/platform/android/src/annotation/polygon.hpp
@@ -0,0 +1,40 @@
+#pragma once
+
+#include <mbgl/annotation/annotation.hpp>
+#include <mbgl/util/color.hpp>
+
+#include <string>
+
+#include "multi_point.hpp"
+
+#include "../geometry/lat_lng.hpp"
+#include "../java/util.hpp"
+
+namespace mbgl {
+namespace android {
+
+class Polygon : private MultiPoint {
+public:
+
+ static constexpr auto Name() { return "com/mapbox/mapboxsdk/annotations/Polygon"; };
+
+ static jni::Class<Polygon> javaClass;
+
+ static mbgl::FillAnnotation toAnnotation(jni::JNIEnv&, jni::Object<Polygon>);
+
+ static void registerNative(jni::JNIEnv&);
+
+private:
+
+ static jni::Object<java::util::List> getPoints(jni::JNIEnv&, jni::Object<Polygon>);
+
+ static float getOpacity(jni::JNIEnv&, jni::Object<Polygon>);
+
+ static mbgl::Color getFillColor(jni::JNIEnv&, jni::Object<Polygon>);
+
+ static mbgl::Color getOutlineColor(jni::JNIEnv&, jni::Object<Polygon>);
+};
+
+
+} // namespace android
+} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/annotation/polyline.cpp b/platform/android/src/annotation/polyline.cpp
new file mode 100644
index 0000000000..3723dc1871
--- /dev/null
+++ b/platform/android/src/annotation/polyline.cpp
@@ -0,0 +1,49 @@
+#include "polyline.hpp"
+
+#include "../conversion/color.hpp"
+
+namespace mbgl {
+namespace android {
+
+jni::Class<Polyline> Polyline::javaClass;
+
+mbgl::LineAnnotation Polyline::toAnnotation(jni::JNIEnv& env, jni::Object<Polyline> polyline) {
+ auto points = Polyline::getPoints(env, polyline);
+
+ mbgl::LineAnnotation annotation { MultiPoint::toGeometry<mbgl::LineString<double>>(env, points) };
+ annotation.opacity = { Polyline::getOpacity(env, polyline) };
+ annotation.color = { Polyline::getColor(env, polyline) };
+ annotation.width = { Polyline::getWidth(env, polyline) };
+
+ jni::DeleteLocalRef(env, points);
+
+ return annotation;
+}
+
+jni::Object<java::util::List> Polyline::getPoints(jni::JNIEnv& env, jni::Object<Polyline> polyline) {
+ static auto field = Polyline::javaClass.GetField<jni::Object<java::util::List>>(env, "points");
+ return polyline.Get(env, field);
+}
+
+float Polyline::getOpacity(jni::JNIEnv& env, jni::Object<Polyline> polyline) {
+ static auto field = Polyline::javaClass.GetField<float>(env, "alpha");
+ return polyline.Get(env, field);
+}
+
+mbgl::Color Polyline::getColor(jni::JNIEnv& env, jni::Object<Polyline> polyline) {
+ static auto field = Polyline::javaClass.GetField<int>(env, "color");
+ return *conversion::convert<mbgl::Color, int>(env, polyline.Get(env, field));
+}
+
+float Polyline::getWidth(jni::JNIEnv& env, jni::Object<Polyline> polyline) {
+ static auto field = Polyline::javaClass.GetField<float>(env, "width");
+ return polyline.Get(env, field);
+}
+
+void Polyline::registerNative(jni::JNIEnv& env) {
+ Polyline::javaClass = *jni::Class<Polyline>::Find(env).NewGlobalRef(env).release();
+}
+
+
+} // namespace android
+} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/annotation/polyline.hpp b/platform/android/src/annotation/polyline.hpp
new file mode 100644
index 0000000000..bcc616a5f7
--- /dev/null
+++ b/platform/android/src/annotation/polyline.hpp
@@ -0,0 +1,40 @@
+#pragma once
+
+#include <mbgl/annotation/annotation.hpp>
+#include <mbgl/util/color.hpp>
+
+#include <string>
+
+#include "multi_point.hpp"
+
+#include "../geometry/lat_lng.hpp"
+#include "../java/util.hpp"
+
+namespace mbgl {
+namespace android {
+
+class Polyline : private MultiPoint {
+public:
+
+ static constexpr auto Name() { return "com/mapbox/mapboxsdk/annotations/Polyline"; };
+
+ static jni::Class<Polyline> javaClass;
+
+ static mbgl::LineAnnotation toAnnotation(jni::JNIEnv&, jni::Object<Polyline>);
+
+ static void registerNative(jni::JNIEnv&);
+
+private:
+
+ static jni::Object<java::util::List> getPoints(jni::JNIEnv&, jni::Object<Polyline>);
+
+ static float getOpacity(jni::JNIEnv&, jni::Object<Polyline>);
+
+ static mbgl::Color getColor(jni::JNIEnv&, jni::Object<Polyline>);
+
+ static float getWidth(jni::JNIEnv&, jni::Object<Polyline>);
+};
+
+
+} // namespace android
+} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/conversion/collection.hpp b/platform/android/src/conversion/collection.hpp
index 0f67c685f4..da5eed64d2 100644
--- a/platform/android/src/conversion/collection.hpp
+++ b/platform/android/src/conversion/collection.hpp
@@ -38,6 +38,19 @@ inline std::vector<std::string> toVector(JNIEnv& env, jni::jarray<jni::jobject>&
return vector;
}
+inline std::vector<std::string> toVector(JNIEnv& env, jni::Array<jni::String> array) {
+ std::vector<std::string> vector;
+ std::size_t len = array.Length(env);
+
+ for (std::size_t i = 0; i < len; i++) {
+ jni::String jstr = array.Get(env, i);
+ vector.push_back(*convert<std::string, jni::String>(env, jstr));
+ jni::DeleteLocalRef(env, jstr);
+ }
+
+ return vector;
+}
+
}
}
}
diff --git a/platform/android/src/conversion/color.hpp b/platform/android/src/conversion/color.hpp
new file mode 100644
index 0000000000..40aa68d4a9
--- /dev/null
+++ b/platform/android/src/conversion/color.hpp
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "conversion.hpp"
+
+#include <mbgl/util/color.hpp>
+
+namespace mbgl {
+namespace android {
+namespace conversion {
+
+template <>
+struct Converter<mbgl::Color, int> {
+ Result<mbgl::Color> operator()(jni::JNIEnv&, const int& color) const {
+ float r = (color >> 16) & 0xFF;
+ float g = (color >> 8) & 0xFF;
+ float b = (color) & 0xFF;
+ float a = (color >> 24) & 0xFF;
+ return { mbgl::Color( r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f ) };
+ }
+};
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/platform/android/src/geometry/conversion/feature.hpp b/platform/android/src/geometry/conversion/feature.hpp
index 18f2741d66..921138e859 100644
--- a/platform/android/src/geometry/conversion/feature.hpp
+++ b/platform/android/src/geometry/conversion/feature.hpp
@@ -3,6 +3,7 @@
#include "../../conversion/constant.hpp"
#include "../../conversion/conversion.hpp"
#include "geometry.hpp"
+#include "../../gson/json_object.hpp"
#include <mbgl/util/feature.hpp>
#include <mapbox/variant.hpp>
@@ -10,6 +11,7 @@
#include <jni/jni.hpp>
#include "../../jni/local_object.hpp"
+#include "../feature.hpp"
#include <string>
#include <array>
@@ -168,39 +170,45 @@ struct Converter<jni::jobject*, std::unordered_map<std::string, mbgl::Value>> {
template <>
-struct Converter<jni::jobject*, mbgl::Feature> {
- Result<jni::jobject*> operator()(jni::JNIEnv& env, const mbgl::Feature& value) const {
- static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/Feature")).release();
- static jni::jmethodID* fromGeometry = &jni::GetStaticMethodID(env, *javaClass, "fromGeometry", "(Lcom/mapbox/services/commons/geojson/Geometry;Lcom/google/gson/JsonObject;Ljava/lang/String;)Lcom/mapbox/services/commons/geojson/Feature;");
+struct Converter<jni::Object<Feature>, mbgl::Feature> {
+ Result<jni::Object<Feature>> operator()(jni::JNIEnv& env, const mbgl::Feature& value) const {
// Convert Id
FeatureIdVisitor idEvaluator;
std::string id = (value.id) ? mapbox::geometry::identifier::visit(value.id.value(), idEvaluator) : "";
- jni::LocalObject<jni::jobject> jid = jni::NewLocalObject(env, *convert<jni::jobject*>(env, id));
+ auto jid = jni::Make<jni::String>(env, id);
// Convert properties
- jni::LocalObject<jni::jobject> properties = jni::NewLocalObject(env, *convert<jni::jobject*>(env, value.properties));
+ auto properties = jni::Object<JsonObject>(*convert<jni::jobject*>(env, value.properties));
// Convert geometry
- jni::LocalObject<jni::jobject> geometry = jni::NewLocalObject(env, *convert<jni::jobject*>(env, value.geometry));
+ auto geometry = jni::Object<Geometry>(*convert<jni::jobject*>(env, value.geometry));
// Create feature
- return {reinterpret_cast<jni::jobject*>(jni::CallStaticMethod<jni::jobject*>(env, *javaClass, *fromGeometry, geometry.get(), properties.get(), jid.get()))};
+ auto feature = Feature::fromGeometry(env, geometry, properties, jid);
+
+ //Cleanup
+ jni::DeleteLocalRef(env, jid);
+ jni::DeleteLocalRef(env, geometry);
+ jni::DeleteLocalRef(env, properties);
+
+ return feature;
}
};
template <>
-struct Converter<jni::jarray<jni::jobject>*, std::vector<mbgl::Feature>> {
- Result<jni::jarray<jni::jobject>*> operator()(jni::JNIEnv& env, const std::vector<mbgl::Feature>& value) const {
- static jni::jclass* featureClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/Feature")).release();
- jni::jarray<jni::jobject>& jarray = jni::NewObjectArray(env, value.size(), *featureClass);
+struct Converter<jni::Array<jni::Object<Feature>>, std::vector<mbgl::Feature>> {
+ Result<jni::Array<jni::Object<Feature>>> operator()(jni::JNIEnv& env, const std::vector<mbgl::Feature>& value) const {
+
+ auto features = jni::Array<jni::Object<Feature>>::New(env, value.size(), Feature::javaClass);
for(size_t i = 0; i < value.size(); i = i + 1) {
- jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, *convert<jni::jobject*, mbgl::Feature>(env, value.at(i)));
- jni::SetObjectArrayElement(env, jarray, i, converted.get());
+ auto converted = *convert<jni::Object<Feature>, mbgl::Feature>(env, value.at(i));
+ features.Set(env, i, converted);
+ jni::DeleteLocalRef(env, converted);
}
- return {&jarray};
+ return {features};
}
};
diff --git a/platform/android/src/geometry/feature.cpp b/platform/android/src/geometry/feature.cpp
new file mode 100644
index 0000000000..5355d50ab7
--- /dev/null
+++ b/platform/android/src/geometry/feature.cpp
@@ -0,0 +1,20 @@
+#include "feature.hpp"
+
+namespace mbgl {
+namespace android {
+
+jni::Object<Feature> Feature::fromGeometry(jni::JNIEnv& env, jni::Object<Geometry> geometry, jni::Object<JsonObject> properties, jni::String id) {
+ static auto method = Feature::javaClass.GetStaticMethod<jni::Object<Feature> (jni::Object<Geometry>, jni::Object<JsonObject>, jni::String)>(env, "fromGeometry");
+ return Feature::javaClass.Call(env, method, geometry, properties, id);
+}
+
+void Feature::registerNative(jni::JNIEnv& env) {
+ // Lookup the class
+ Feature::javaClass = *jni::Class<Feature>::Find(env).NewGlobalRef(env).release();
+}
+
+jni::Class<Feature> Feature::javaClass;
+
+
+} // namespace android
+} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/geometry/feature.hpp b/platform/android/src/geometry/feature.hpp
new file mode 100644
index 0000000000..7f2733430c
--- /dev/null
+++ b/platform/android/src/geometry/feature.hpp
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <mbgl/util/noncopyable.hpp>
+#include <mbgl/util/geometry.hpp>
+
+#include <jni/jni.hpp>
+
+#include "geometry.hpp"
+#include "../gson/json_object.hpp"
+
+namespace mbgl {
+namespace android {
+
+class Feature : private mbgl::util::noncopyable {
+public:
+
+ static constexpr auto Name() { return "com/mapbox/services/commons/geojson/Feature"; };
+
+ static jni::Object<Feature> fromGeometry(jni::JNIEnv&, jni::Object<Geometry>, jni::Object<JsonObject>, jni::String);
+
+ static jni::Class<Feature> javaClass;
+
+ static void registerNative(jni::JNIEnv&);
+
+};
+
+
+} // namespace android
+} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/geometry/geometry.hpp b/platform/android/src/geometry/geometry.hpp
new file mode 100644
index 0000000000..5c8ae39181
--- /dev/null
+++ b/platform/android/src/geometry/geometry.hpp
@@ -0,0 +1,16 @@
+#pragma once
+
+#include <mbgl/util/noncopyable.hpp>
+
+namespace mbgl {
+namespace android {
+
+class Geometry : private mbgl::util::noncopyable {
+public:
+ static constexpr auto Name() { return "com/mapbox/services/commons/geojson/Geometry"; };
+
+};
+
+
+} // namespace android
+} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/geometry/lat_lng.cpp b/platform/android/src/geometry/lat_lng.cpp
new file mode 100644
index 0000000000..9cf3630107
--- /dev/null
+++ b/platform/android/src/geometry/lat_lng.cpp
@@ -0,0 +1,31 @@
+#include "lat_lng.hpp"
+
+namespace mbgl {
+namespace android {
+
+jni::Object<LatLng> LatLng::New(jni::JNIEnv& env, double latitude, double longitude) {
+ static auto constructor = LatLng::javaClass.GetConstructor<double, double>(env);
+ return LatLng::javaClass.New(env, constructor, latitude, longitude);
+}
+
+mbgl::Point<double> LatLng::getGeometry(jni::JNIEnv& env, jni::Object<LatLng> latLng) {
+ static auto latitudeField = LatLng::javaClass.GetField<jni::jdouble>(env, "latitude");
+ static auto longitudeField = LatLng::javaClass.GetField<jni::jdouble>(env, "longitude");
+ return mbgl::Point<double>(latLng.Get(env, longitudeField), latLng.Get(env, latitudeField));
+}
+
+mbgl::LatLng LatLng::getLatLng(jni::JNIEnv& env, jni::Object<LatLng> latLng) {
+ auto point = LatLng::getGeometry(env, latLng);
+ return mbgl::LatLng(point.y, point.x);
+}
+
+void LatLng::registerNative(jni::JNIEnv& env) {
+ // Lookup the class
+ LatLng::javaClass = *jni::Class<LatLng>::Find(env).NewGlobalRef(env).release();
+}
+
+jni::Class<LatLng> LatLng::javaClass;
+
+
+} // namespace android
+} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/geometry/lat_lng.hpp b/platform/android/src/geometry/lat_lng.hpp
new file mode 100644
index 0000000000..1ac32ae32e
--- /dev/null
+++ b/platform/android/src/geometry/lat_lng.hpp
@@ -0,0 +1,31 @@
+#pragma once
+
+#include <mbgl/util/noncopyable.hpp>
+#include <mbgl/util/geo.hpp>
+#include <mbgl/util/geometry.hpp>
+
+#include <jni/jni.hpp>
+
+namespace mbgl {
+namespace android {
+
+class LatLng : private mbgl::util::noncopyable {
+public:
+
+ static constexpr auto Name() { return "com/mapbox/mapboxsdk/geometry/LatLng"; };
+
+ static jni::Object<LatLng> New(jni::JNIEnv&, double, double);
+
+ static mbgl::Point<double> getGeometry(jni::JNIEnv&, jni::Object<LatLng>);
+
+ static mbgl::LatLng getLatLng(jni::JNIEnv&, jni::Object<LatLng>);
+
+ static jni::Class<LatLng> javaClass;
+
+ static void registerNative(jni::JNIEnv&);
+
+};
+
+
+} // namespace android
+} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/geometry/projected_meters.cpp b/platform/android/src/geometry/projected_meters.cpp
new file mode 100644
index 0000000000..f3d9d1b0ef
--- /dev/null
+++ b/platform/android/src/geometry/projected_meters.cpp
@@ -0,0 +1,20 @@
+#include "projected_meters.hpp"
+
+namespace mbgl {
+namespace android {
+
+jni::Object<ProjectedMeters> ProjectedMeters::New(jni::JNIEnv& env, double northing, double easting) {
+ static auto constructor = ProjectedMeters::javaClass.GetConstructor<double, double>(env);
+ return ProjectedMeters::javaClass.New(env, constructor, northing, easting);
+}
+
+void ProjectedMeters::registerNative(jni::JNIEnv& env) {
+ // Lookup the class
+ ProjectedMeters::javaClass = *jni::Class<ProjectedMeters>::Find(env).NewGlobalRef(env).release();
+}
+
+jni::Class<ProjectedMeters> ProjectedMeters::javaClass;
+
+
+} // namespace android
+} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/geometry/projected_meters.hpp b/platform/android/src/geometry/projected_meters.hpp
new file mode 100644
index 0000000000..9b70967b5d
--- /dev/null
+++ b/platform/android/src/geometry/projected_meters.hpp
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <mbgl/util/noncopyable.hpp>
+#include <mbgl/util/geometry.hpp>
+
+#include <jni/jni.hpp>
+
+namespace mbgl {
+namespace android {
+
+class ProjectedMeters : private mbgl::util::noncopyable {
+public:
+
+ static constexpr auto Name() { return "com/mapbox/mapboxsdk/geometry/ProjectedMeters"; };
+
+ static jni::Object<ProjectedMeters> New(jni::JNIEnv&, double, double);
+
+ static jni::Class<ProjectedMeters> javaClass;
+
+ static void registerNative(jni::JNIEnv&);
+
+};
+
+
+} // namespace android
+} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/graphics/pointf.cpp b/platform/android/src/graphics/pointf.cpp
new file mode 100644
index 0000000000..6e91b81416
--- /dev/null
+++ b/platform/android/src/graphics/pointf.cpp
@@ -0,0 +1,20 @@
+#include "pointf.hpp"
+
+namespace mbgl {
+namespace android {
+
+jni::Object<PointF> PointF::New(jni::JNIEnv& env, float x, float y) {
+ static auto constructor = PointF::javaClass.GetConstructor<float, float>(env);
+ return PointF::javaClass.New(env, constructor, x, y);
+}
+
+void PointF::registerNative(jni::JNIEnv& env) {
+ // Lookup the class
+ PointF::javaClass = *jni::Class<PointF>::Find(env).NewGlobalRef(env).release();
+}
+
+jni::Class<PointF> PointF::javaClass;
+
+
+} // namespace android
+} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/graphics/pointf.hpp b/platform/android/src/graphics/pointf.hpp
new file mode 100644
index 0000000000..ea25ad2b40
--- /dev/null
+++ b/platform/android/src/graphics/pointf.hpp
@@ -0,0 +1,25 @@
+#pragma once
+
+#include <mbgl/util/noncopyable.hpp>
+
+#include <jni/jni.hpp>
+
+namespace mbgl {
+namespace android {
+
+class PointF : private mbgl::util::noncopyable {
+public:
+
+ static constexpr auto Name() { return "android/graphics/PointF"; };
+
+ static jni::Object<PointF> New(jni::JNIEnv&, float, float);
+
+ static jni::Class<PointF> javaClass;
+
+ static void registerNative(jni::JNIEnv&);
+
+};
+
+
+} // namespace android
+} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/graphics/rectf.cpp b/platform/android/src/graphics/rectf.cpp
new file mode 100644
index 0000000000..1b375dad18
--- /dev/null
+++ b/platform/android/src/graphics/rectf.cpp
@@ -0,0 +1,35 @@
+#include "rectf.hpp"
+
+namespace mbgl {
+namespace android {
+
+float RectF::getLeft(jni::JNIEnv& env, jni::Object<RectF> rectf) {
+ static auto field = RectF::javaClass.GetField<float>(env, "left");
+ return rectf.Get(env, field);
+}
+
+float RectF::getTop(jni::JNIEnv& env, jni::Object<RectF> rectf) {
+ static auto field = RectF::javaClass.GetField<float>(env, "top");
+ return rectf.Get(env, field);
+}
+
+float RectF::getRight(jni::JNIEnv& env, jni::Object<RectF> rectf) {
+ static auto field = RectF::javaClass.GetField<float>(env, "right");
+ return rectf.Get(env, field);
+}
+
+float RectF::getBottom(jni::JNIEnv& env, jni::Object<RectF> rectf) {
+ static auto field = RectF::javaClass.GetField<float>(env, "bottom");
+ return rectf.Get(env, field);
+}
+
+void RectF::registerNative(jni::JNIEnv& env) {
+ // Lookup the class
+ RectF::javaClass = *jni::Class<RectF>::Find(env).NewGlobalRef(env).release();
+}
+
+jni::Class<RectF> RectF::javaClass;
+
+
+} // namespace android
+} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/graphics/rectf.hpp b/platform/android/src/graphics/rectf.hpp
new file mode 100644
index 0000000000..0f3a7756d5
--- /dev/null
+++ b/platform/android/src/graphics/rectf.hpp
@@ -0,0 +1,31 @@
+#pragma once
+
+#include <mbgl/util/noncopyable.hpp>
+
+#include <jni/jni.hpp>
+
+namespace mbgl {
+namespace android {
+
+class RectF : private mbgl::util::noncopyable {
+public:
+
+ static constexpr auto Name() { return "android/graphics/RectF"; };
+
+ static float getLeft(jni::JNIEnv&, jni::Object<RectF>);
+
+ static float getTop(jni::JNIEnv&, jni::Object<RectF>);
+
+ static float getRight(jni::JNIEnv&, jni::Object<RectF>);
+
+ static float getBottom(jni::JNIEnv&, jni::Object<RectF>);
+
+ static jni::Class<RectF> javaClass;
+
+ static void registerNative(jni::JNIEnv&);
+
+};
+
+
+} // namespace android
+} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/gson/json_object.hpp b/platform/android/src/gson/json_object.hpp
new file mode 100644
index 0000000000..a7de0b1978
--- /dev/null
+++ b/platform/android/src/gson/json_object.hpp
@@ -0,0 +1,16 @@
+#pragma once
+
+#include <mbgl/util/noncopyable.hpp>
+
+namespace mbgl {
+namespace android {
+
+class JsonObject : private mbgl::util::noncopyable {
+public:
+ static constexpr auto Name() { return "com/google/gson/JsonObject"; };
+
+};
+
+
+} // namespace android
+} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/java/util.cpp b/platform/android/src/java/util.cpp
new file mode 100644
index 0000000000..c630e403d9
--- /dev/null
+++ b/platform/android/src/java/util.cpp
@@ -0,0 +1,18 @@
+#include "util.hpp"
+
+namespace mbgl {
+namespace android {
+namespace java {
+namespace util {
+
+jni::Class<List> List::javaClass;
+
+void registerNative(jni::JNIEnv& env) {
+ List::javaClass = *jni::Class<List>::Find(env).NewGlobalRef(env).release();
+}
+
+
+} // namespace util
+} // namespace java
+} // namespace android
+} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/java/util.hpp b/platform/android/src/java/util.hpp
new file mode 100644
index 0000000000..1a552c7124
--- /dev/null
+++ b/platform/android/src/java/util.hpp
@@ -0,0 +1,33 @@
+#pragma once
+
+#include <mbgl/util/noncopyable.hpp>
+
+#include <jni/jni.hpp>
+
+namespace mbgl {
+namespace android {
+namespace java {
+namespace util {
+
+class List : private mbgl::util::noncopyable {
+public:
+
+ static constexpr auto Name() { return "java/util/List"; };
+
+ template<class T>
+ static jni::Array<jni::Object<T>> toArray(jni::JNIEnv& env, jni::Object<List> list) {
+ static auto toArray = List::javaClass.GetMethod<jni::Array<jni::Object<>> ()>(env, "toArray");
+ return (jni::Array<jni::Object<T>>) list.Call(env, toArray);
+ };
+
+ static jni::Class<List> javaClass;
+
+};
+
+void registerNative(jni::JNIEnv&);
+
+
+} // namespace util
+} // namespace java
+} // namespace android
+} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/jni.cpp b/platform/android/src/jni.cpp
index 3acb987445..e1164d3d2a 100755
--- a/platform/android/src/jni.cpp
+++ b/platform/android/src/jni.cpp
@@ -19,12 +19,19 @@
#include "style/functions/identity_stops.hpp"
#include "style/functions/interval_stops.hpp"
#include "style/functions/stop.hpp"
+#include "annotation/marker.hpp"
+#include "annotation/polygon.hpp"
+#include "annotation/polyline.hpp"
+#include "graphics/pointF.hpp"
+#include "graphics/rectF.hpp"
+#include "geometry/feature.hpp"
+#include "geometry/lat_lng.hpp"
+#include "geometry/projected_meters.hpp"
#include "style/layers/layers.hpp"
#include "style/sources/sources.hpp"
#include "conversion/conversion.hpp"
#include "conversion/collection.hpp"
-#include "geometry/conversion/feature.hpp"
#include <mbgl/map/map.hpp>
#include <mbgl/map/camera.hpp>
@@ -42,8 +49,6 @@
#include <mapbox/geometry.hpp>
-#include <jni/jni.hpp>
-
#pragma clang diagnostic ignored "-Wunused-parameter"
namespace mbgl {
@@ -58,17 +63,6 @@ std::string dataPath;
std::string apkPath;
std::string androidRelease;
-jni::jmethodID* onInvalidateId = nullptr;
-jni::jmethodID* wakeCallbackId = nullptr;
-jni::jmethodID* onMapChangedId = nullptr;
-jni::jmethodID* onFpsChangedId = nullptr;
-jni::jmethodID* onSnapshotReadyId = nullptr;
-
-jni::jclass* latLngClass = nullptr;
-jni::jmethodID* latLngConstructorId = nullptr;
-jni::jfieldID* latLngLatitudeId = nullptr;
-jni::jfieldID* latLngLongitudeId = nullptr;
-
jni::jclass* latLngBoundsClass = nullptr;
jni::jmethodID* latLngBoundsConstructorId = nullptr;
jni::jfieldID* latLngBoundsLatNorthId = nullptr;
@@ -76,49 +70,6 @@ jni::jfieldID* latLngBoundsLatSouthId = nullptr;
jni::jfieldID* latLngBoundsLonEastId = nullptr;
jni::jfieldID* latLngBoundsLonWestId = nullptr;
-jni::jclass* iconClass = nullptr;
-jni::jfieldID* iconIdId = nullptr;
-
-jni::jclass* markerClass = nullptr;
-jni::jfieldID* markerPositionId = nullptr;
-jni::jfieldID* markerIconId = nullptr;
-jni::jfieldID* markerIdId = nullptr;
-
-jni::jclass* polylineClass = nullptr;
-jni::jfieldID* polylineAlphaId = nullptr;
-jni::jfieldID* polylineColorId = nullptr;
-jni::jfieldID* polylineWidthId = nullptr;
-jni::jfieldID* polylinePointsId = nullptr;
-
-jni::jclass* polygonClass = nullptr;
-jni::jfieldID* polygonAlphaId = nullptr;
-jni::jfieldID* polygonFillColorId = nullptr;
-jni::jfieldID* polygonStrokeColorId = nullptr;
-jni::jfieldID* polygonPointsId = nullptr;
-
-jni::jmethodID* listToArrayId = nullptr;
-
-jni::jclass* arrayListClass = nullptr;
-jni::jmethodID* arrayListConstructorId = nullptr;
-jni::jmethodID* arrayListAddId = nullptr;
-
-jni::jclass* projectedMetersClass = nullptr;
-jni::jmethodID* projectedMetersConstructorId = nullptr;
-jni::jfieldID* projectedMetersNorthingId = nullptr;
-jni::jfieldID* projectedMetersEastingId = nullptr;
-
-jni::jclass* pointFClass = nullptr;
-jni::jmethodID* pointFConstructorId = nullptr;
-jni::jfieldID* pointFXId = nullptr;
-jni::jfieldID* pointFYId = nullptr;
-
-jni::jclass* rectFClass = nullptr;
-jni::jmethodID* rectFConstructorId = nullptr;
-jni::jfieldID* rectFLeftId = nullptr;
-jni::jfieldID* rectFTopId = nullptr;
-jni::jfieldID* rectFRightId = nullptr;
-jni::jfieldID* rectFBottomId = nullptr;
-
// Offline declarations start
jni::jfieldID* offlineManagerClassPtrId = nullptr;
@@ -224,46 +175,6 @@ jni::jstring* std_string_to_jstring(JNIEnv *env, std::string str) {
return jni::Make<jni::String>(*env, str).Get();
}
-std::vector<std::string> std_vector_string_from_jobject(JNIEnv *env, jni::jobject* jlist) {
- std::vector<std::string> vector;
-
- jni::NullCheck(*env, jlist);
- jni::jarray<jni::jobject>* jarray =
- reinterpret_cast<jni::jarray<jni::jobject>*>(jni::CallMethod<jni::jobject*>(*env, jlist, *listToArrayId));
-
- jni::NullCheck(*env, jarray);
- std::size_t len = jni::GetArrayLength(*env, *jarray);
-
- for (std::size_t i = 0; i < len; i++) {
- jni::jstring* jstr = reinterpret_cast<jni::jstring*>(jni::GetObjectArrayElement(*env, *jarray, i));
- vector.push_back(std_string_from_jstring(env, jstr));
- }
-
- return vector;
-}
-
-jni::jobject* std_vector_string_to_jobject(JNIEnv *env, std::vector<std::string> vector) {
- jni::jobject* jlist = &jni::NewObject(*env, *arrayListClass, *arrayListConstructorId);
-
- for (const auto& str : vector) {
- jni::CallMethod<jboolean>(*env, jlist, *arrayListAddId, std_string_to_jstring(env, str));
- }
-
- return jlist;
-}
-
-jni::jarray<jlong>* std_vector_uint_to_jobject(JNIEnv *env, const std::vector<uint32_t>& vector) {
- jni::jarray<jlong>& jarray = jni::NewArray<jlong>(*env, vector.size());
-
- std::vector<jlong> v;
- v.reserve(vector.size());
- std::move(vector.begin(), vector.end(), std::back_inserter(v));
-
- jni::SetArrayRegion(*env, jarray, 0, v);
-
- return &jarray;
-}
-
static std::vector<uint8_t> metadata_from_java(JNIEnv* env, jni::jarray<jbyte>& j) {
std::size_t length = jni::GetArrayLength(*env, j);
std::vector<uint8_t> c;
@@ -307,939 +218,6 @@ namespace {
using namespace mbgl::android;
using DebugOptions = mbgl::MapDebugOptions;
-jlong nativeCreate(JNIEnv *env, jni::jobject* obj, jni::jstring* cachePath_, jni::jstring* dataPath_, jni::jstring* apkPath_, jfloat pixelRatio, jint availableProcessors, jlong totalMemory) {
- mbgl::Log::Info(mbgl::Event::JNI, "nativeCreate");
- cachePath = std_string_from_jstring(env, cachePath_);
- dataPath = std_string_from_jstring(env, dataPath_);
- apkPath = std_string_from_jstring(env, apkPath_);
-
- mbgl::Log::Info(mbgl::Event::JNI, "Create NativeMapView");
- return reinterpret_cast<jlong>(new NativeMapView(env, jni::Unwrap(obj), pixelRatio, availableProcessors, totalMemory));
-}
-
-void nativeDestroy(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- mbgl::Log::Info(mbgl::Event::JNI, "nativeDestroy");
- assert(nativeMapViewPtr != 0);
- delete reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
-}
-
-void nativeUpdate(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->invalidate();
-}
-
-void nativeRender(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- mbgl::Log::Info(mbgl::Event::JNI, "nativeRender");
- mbgl::util::RunLoop::Get()->runOnce();
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->render();
-}
-
-void nativeOnViewportChanged(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jint width, jint height) {
- mbgl::Log::Info(mbgl::Event::JNI, "nativeViewResize");
- assert(nativeMapViewPtr != 0);
- assert(width >= 0);
- assert(height >= 0);
- assert(width <= UINT16_MAX);
- assert(height <= UINT16_MAX);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->onViewportChanged(width, height);
-}
-
-void nativeRemoveClass(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* clazz) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->getMap().removeClass(std_string_from_jstring(env, clazz));
-}
-
-jboolean nativeHasClass(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* clazz) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- return nativeMapView->getMap().hasClass(std_string_from_jstring(env, clazz));
-}
-
-void nativeAddClass(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* clazz) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->getMap().addClass(std_string_from_jstring(env, clazz));
-}
-
-void nativeSetClasses(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jobject* classes) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->getMap().setClasses(std_vector_string_from_jobject(env, classes));
-}
-
-jni::jobject* nativeGetClasses(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- return std_vector_string_to_jobject(env, nativeMapView->getMap().getClasses());
-}
-
-void nativeSetAPIBaseURL(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* url) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->getFileSource().setAPIBaseURL(std_string_from_jstring(env, url));
-}
-
-void nativeSetStyleUrl(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* url) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->getMap().setStyleURL(std_string_from_jstring(env, url));
-}
-
-jni::jstring* nativeGetStyleUrl(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr){
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- return std_string_to_jstring(env, nativeMapView->getMap().getStyleURL());
-}
-
-void nativeSetStyleJson(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* newStyleJson) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->getMap().setStyleJSON(std_string_from_jstring(env, newStyleJson));
-}
-
-jni::jstring* nativeGetStyleJson(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- return std_string_to_jstring(env, nativeMapView->getMap().getStyleJSON());
-}
-
-void nativeSetAccessToken(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* accessToken) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->getFileSource().setAccessToken(std_string_from_jstring(env, accessToken));
-}
-
-jni::jstring* nativeGetAccessToken(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- return std_string_to_jstring(env, nativeMapView->getFileSource().getAccessToken());
-}
-
-void nativeCancelTransitions(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->getMap().cancelTransitions();
-}
-
-void nativeSetGestureInProgress(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jboolean inProgress) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->getMap().setGestureInProgress(inProgress);
-}
-
-void nativeMoveBy(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble dx, jdouble dy,
- jlong duration) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->getMap().moveBy({dx, dy}, mbgl::Milliseconds(duration));
-}
-
-void nativeSetLatLng(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble latitude, jdouble longitude, jlong duration) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->getMap().setLatLng(mbgl::LatLng(latitude, longitude), nativeMapView->getInsets(), mbgl::Duration(duration));
-}
-
-jni::jobject* nativeGetLatLng(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- mbgl::LatLng latLng = nativeMapView->getMap().getLatLng(nativeMapView->getInsets());
- return &jni::NewObject(*env, *latLngClass, *latLngConstructorId, latLng.latitude, latLng.longitude);
-}
-
-jdoubleArray nativeGetCameraValues(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- mbgl::LatLng latLng = nativeMapView->getMap().getLatLng(nativeMapView->getInsets());
- jdoubleArray output = env->NewDoubleArray(5);
- jsize start = 0;
- jsize leng = 5;
- jdouble buf[5];
- buf[0] = latLng.latitude;
- buf[1] = latLng.longitude;
- buf[2] = -nativeMapView->getMap().getBearing();
- buf[3] = nativeMapView->getMap().getPitch();
- buf[4] = nativeMapView->getMap().getZoom();
- env->SetDoubleArrayRegion(output, start, leng, buf);
-
- if (output == nullptr) {
- env->ExceptionDescribe();
- return nullptr;
- }
-
- return output;
-}
-
-void nativeResetPosition(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->getMap().resetPosition();
-}
-
-jdouble nativeGetPitch(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- return nativeMapView->getMap().getPitch();
-}
-
-void nativeSetPitch(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble pitch, jlong milliseconds) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- mbgl::Duration duration((mbgl::Milliseconds(milliseconds)));
- nativeMapView->getMap().setPitch(pitch, duration);
-}
-
-void nativeScaleBy(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble ds, jdouble cx,
- jdouble cy, jlong duration) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- mbgl::ScreenCoordinate center(cx, cy);
- nativeMapView->getMap().scaleBy(ds, center, mbgl::Milliseconds(duration));
-}
-
-void nativeSetScale(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble scale,
- jdouble cx, jdouble cy, jlong duration) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- mbgl::ScreenCoordinate center(cx, cy);
- nativeMapView->getMap().setScale(scale, center, mbgl::Milliseconds(duration));
-}
-
-jdouble nativeGetScale(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- return nativeMapView->getMap().getScale();
-}
-
-void nativeSetZoom(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble zoom, jlong duration) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->getMap().setZoom(zoom, mbgl::Milliseconds(duration));
-}
-
-jdouble nativeGetZoom(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- return nativeMapView->getMap().getZoom();
-}
-
-void nativeResetZoom(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->getMap().resetZoom();
-}
-
-void nativeSetMinZoom(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble zoom) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->getMap().setMinZoom(zoom);
-}
-
-jdouble nativeGetMinZoom(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- return nativeMapView->getMap().getMinZoom();
-}
-
-void nativeSetMaxZoom(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble zoom) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->getMap().setMaxZoom(zoom);
-}
-
-jdouble nativeGetMaxZoom(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- return nativeMapView->getMap().getMaxZoom();
-}
-
-void nativeRotateBy(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble sx,
- jdouble sy, jdouble ex, jdouble ey, jlong duration) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- mbgl::ScreenCoordinate first(sx, sy);
- mbgl::ScreenCoordinate second(ex, ey);
- nativeMapView->getMap().rotateBy(first, second, mbgl::Milliseconds(duration));
-}
-
-void nativeSetBearing(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble degrees,
- jlong milliseconds) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- mbgl::Duration duration((mbgl::Milliseconds(milliseconds)));
- nativeMapView->getMap().setBearing(degrees, duration);
-}
-
-void nativeSetFocalBearing(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble degrees, jdouble fx,
- jdouble fy, jlong milliseconds) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- mbgl::ScreenCoordinate center(fx, fy);
- nativeMapView->getMap().setBearing(degrees, center, mbgl::Milliseconds(milliseconds));
-}
-
-void nativeSetBearingXY(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble degrees,
- jdouble cx, jdouble cy) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- mbgl::ScreenCoordinate center(cx, cy);
- nativeMapView->getMap().setBearing(degrees, center);
-}
-
-jdouble nativeGetBearing(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- return nativeMapView->getMap().getBearing();
-}
-
-void nativeResetNorth(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->getMap().resetNorth();
-}
-
-void nativeUpdateMarker(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jlong markerId, jdouble lat, jdouble lon, jni::jstring* jid) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- if (markerId == -1) {
- return;
- }
- std::string iconId = std_string_from_jstring(env, jid);
- // Because Java only has int, not unsigned int, we need to bump the annotation id up to a long.
- nativeMapView->getMap().updateAnnotation(markerId, mbgl::SymbolAnnotation { mbgl::Point<double>(lon, lat), iconId });
-}
-
-jni::jarray<jlong>* nativeAddMarkers(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jarray<jni::jobject>* jarray) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
-
- NullCheck(*env, jarray);
- std::size_t len = jni::GetArrayLength(*env, *jarray);
-
- mbgl::AnnotationIDs ids;
- ids.reserve(len);
-
- for (std::size_t i = 0; i < len; i++) {
- jni::jobject* marker = jni::GetObjectArrayElement(*env, *jarray, i);
- jni::jobject* position = jni::GetField<jni::jobject*>(*env, marker, *markerPositionId);
- jni::jobject* icon = jni::GetField<jni::jobject*>(*env, marker, *markerIconId);
- jni::jstring* jid = reinterpret_cast<jni::jstring*>(jni::GetField<jni::jobject*>(*env, icon, *iconIdId));
-
- jdouble latitude = jni::GetField<jdouble>(*env, position, *latLngLatitudeId);
- jdouble longitude = jni::GetField<jdouble>(*env, position, *latLngLongitudeId);
-
- ids.push_back(nativeMapView->getMap().addAnnotation(mbgl::SymbolAnnotation {
- mbgl::Point<double>(longitude, latitude),
- std_string_from_jstring(env, jid)
- }));
-
- jni::DeleteLocalRef(*env, position);
- jni::DeleteLocalRef(*env, jid);
- jni::DeleteLocalRef(*env, icon);
- jni::DeleteLocalRef(*env, marker);
- }
-
- return std_vector_uint_to_jobject(env, ids);
-}
-
-static mbgl::Color toColor(jint color) {
- float r = (color >> 16) & 0xFF;
- float g = (color >> 8) & 0xFF;
- float b = (color) & 0xFF;
- float a = (color >> 24) & 0xFF;
- return { r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f };
-}
-
-template <class Geometry>
-Geometry toGeometry(JNIEnv *env, jni::jobject* jlist) {
- NullCheck(*env, jlist);
- jni::jarray<jni::jobject>* jarray =
- reinterpret_cast<jni::jarray<jni::jobject>*>(jni::CallMethod<jni::jobject*>(*env, jlist, *listToArrayId));
- NullCheck(*env, jarray);
-
- std::size_t size = jni::GetArrayLength(*env, *jarray);
-
- Geometry geometry;
- geometry.reserve(size);
-
- for (std::size_t i = 0; i < size; i++) {
- jni::jobject* latLng = reinterpret_cast<jni::jobject*>(jni::GetObjectArrayElement(*env, *jarray, i));
- NullCheck(*env, latLng);
-
- geometry.push_back(mbgl::Point<double>(
- jni::GetField<jdouble>(*env, latLng, *latLngLongitudeId),
- jni::GetField<jdouble>(*env, latLng, *latLngLatitudeId)));
-
- jni::DeleteLocalRef(*env, latLng);
- }
-
- jni::DeleteLocalRef(*env, jarray);
- jni::DeleteLocalRef(*env, jlist);
-
- return geometry;
-}
-
-jni::jarray<jlong>* nativeAddPolylines(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jarray<jni::jobject>* jarray) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
-
- NullCheck(*env, jarray);
- std::size_t len = jni::GetArrayLength(*env, *jarray);
-
- mbgl::AnnotationIDs ids;
- ids.reserve(len);
-
- for (std::size_t i = 0; i < len; i++) {
- jni::jobject* polyline = jni::GetObjectArrayElement(*env, *jarray, i);
- jni::jobject* points = jni::GetField<jni::jobject*>(*env, polyline, *polylinePointsId);
-
- mbgl::LineAnnotation annotation { toGeometry<mbgl::LineString<double>>(env, points) };
- annotation.opacity = { jni::GetField<jfloat>(*env, polyline, *polylineAlphaId) };
- annotation.color = { toColor(jni::GetField<jint>(*env, polyline, *polylineColorId)) };
- annotation.width = { jni::GetField<jfloat>(*env, polyline, *polylineWidthId) };
- ids.push_back(nativeMapView->getMap().addAnnotation(annotation));
-
- jni::DeleteLocalRef(*env, polyline);
- }
-
- return std_vector_uint_to_jobject(env, ids);
-}
-
-jni::jarray<jlong>* nativeAddPolygons(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jarray<jni::jobject>* jarray) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
-
- NullCheck(*env, jarray);
- std::size_t len = jni::GetArrayLength(*env, *jarray);
-
- mbgl::AnnotationIDs ids;
- ids.reserve(len);
-
- for (std::size_t i = 0; i < len; i++) {
- jni::jobject* polygon = jni::GetObjectArrayElement(*env, *jarray, i);
- jni::jobject* points = jni::GetField<jni::jobject*>(*env, polygon, *polygonPointsId);
-
- mbgl::FillAnnotation annotation { mbgl::Polygon<double> { toGeometry<mbgl::LinearRing<double>>(env, points) } };
- annotation.opacity = { jni::GetField<jfloat>(*env, polygon, *polygonAlphaId) };
- annotation.outlineColor = { toColor(jni::GetField<jint>(*env, polygon, *polygonStrokeColorId)) };
- annotation.color = { toColor(jni::GetField<jint>(*env, polygon, *polygonFillColorId)) };
- ids.push_back(nativeMapView->getMap().addAnnotation(annotation));
-
- jni::DeleteLocalRef(*env, polygon);
- }
-
- return std_vector_uint_to_jobject(env, ids);
-}
-
-void nativeUpdatePolygon(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jlong polygonId, jni::jobject* polygon) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- jni::jobject* points = jni::GetField<jni::jobject*>(*env, polygon, *polygonPointsId);
-
- mbgl::FillAnnotation annotation { mbgl::Polygon<double> { toGeometry<mbgl::LinearRing<double>>(env, points) } };
- annotation.opacity = { jni::GetField<jfloat>(*env, polygon, *polygonAlphaId) };
- annotation.outlineColor = { toColor(jni::GetField<jint>(*env, polygon, *polygonStrokeColorId)) };
- annotation.color = { toColor(jni::GetField<jint>(*env, polygon, *polygonFillColorId)) };
- nativeMapView->getMap().updateAnnotation(polygonId, annotation);
-}
-
-void nativeUpdatePolyline(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jlong polylineId, jni::jobject* polyline) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- jni::jobject* points = jni::GetField<jni::jobject*>(*env, polyline, *polylinePointsId);
-
- mbgl::LineAnnotation annotation { toGeometry<mbgl::LineString<double>>(env, points) };
- annotation.opacity = { jni::GetField<jfloat>(*env, polyline, *polylineAlphaId) };
- annotation.color = { toColor(jni::GetField<jint>(*env, polyline, *polylineColorId)) };
- annotation.width = { jni::GetField<jfloat>(*env, polyline, *polylineWidthId) };
- nativeMapView->getMap().updateAnnotation(polylineId, annotation);
-}
-
-void nativeRemoveAnnotations(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jarray<jlong>* jarray) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
-
- NullCheck(*env, jarray);
- std::size_t len = jni::GetArrayLength(*env, *jarray);
- auto elements = jni::GetArrayElements(*env, *jarray);
- jlong* jids = std::get<0>(elements).get();
-
- for (std::size_t i = 0; i < len; i++) {
- if(jids[i] == -1L)
- continue;
- nativeMapView->getMap().removeAnnotation(jids[i]);
- }
-}
-
-jni::jarray<jlong>* nativeQueryPointAnnotations(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jobject* rect) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
-
- // Conversion
- jfloat left = jni::GetField<jfloat>(*env, rect, *rectFLeftId);
- jfloat right = jni::GetField<jfloat>(*env, rect, *rectFRightId);
- jfloat top = jni::GetField<jfloat>(*env, rect, *rectFTopId);
- jfloat bottom = jni::GetField<jfloat>(*env, rect, *rectFBottomId);
- mbgl::ScreenBox box = {
- { left, top },
- { right, bottom },
- };
-
- // Assume only points for now
- mbgl::AnnotationIDs ids = nativeMapView->getMap().queryPointAnnotations(box);
-
- return std_vector_uint_to_jobject(env, ids);
-}
-
-void nativeAddAnnotationIcon(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr,
- jni::jstring* symbol, jint width, jint height, jfloat scale, jni::jarray<jbyte>* jpixels) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
-
- const std::string symbolName = std_string_from_jstring(env, symbol);
-
- NullCheck(*env, jpixels);
- std::size_t size = jni::GetArrayLength(*env, *jpixels);
- mbgl::PremultipliedImage premultipliedImage(
- { static_cast<uint32_t>(width), static_cast<uint32_t>(height) });
-
- if (premultipliedImage.bytes() != uint32_t(size)) {
- throw mbgl::util::SpriteImageException("Sprite image pixel count mismatch");
- }
-
- jni::GetArrayRegion(*env, *jpixels, 0, size, reinterpret_cast<jbyte*>(premultipliedImage.data.get()));
-
- auto iconImage = std::make_shared<mbgl::SpriteImage>(
- std::move(premultipliedImage),
- float(scale));
-
- nativeMapView->getMap().addAnnotationIcon(symbolName, iconImage);
-}
-
-void nativeSetVisibleCoordinateBounds(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr,
- jni::jarray<jni::jobject>* coordinates, jni::jobject* padding, jdouble direction, jlong duration) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
-
- jfloat left = jni::GetField<jfloat>(*env, padding, *rectFLeftId);
- jfloat right = jni::GetField<jfloat>(*env, padding, *rectFRightId);
- jfloat top = jni::GetField<jfloat>(*env, padding, *rectFTopId);
- jfloat bottom = jni::GetField<jfloat>(*env, padding, *rectFBottomId);
-
- NullCheck(*env, coordinates);
- std::size_t count = jni::GetArrayLength(*env, *coordinates);
-
- mbgl::EdgeInsets mbglInsets = {top, left, bottom, right};
- std::vector<mbgl::LatLng> latLngs;
- latLngs.reserve(count);
-
- for (std::size_t i = 0; i < count; i++) {
- jni::jobject* latLng = jni::GetObjectArrayElement(*env, *coordinates, i);
- jdouble latitude = jni::GetField<jdouble>(*env, latLng, *latLngLatitudeId);
- jdouble longitude = jni::GetField<jdouble>(*env, latLng, *latLngLongitudeId);
- latLngs.push_back(mbgl::LatLng(latitude, longitude));
- }
-
- mbgl::CameraOptions cameraOptions = nativeMapView->getMap().cameraForLatLngs(latLngs, mbglInsets);
- if (direction >= 0) {
- // convert from degrees to radians
- cameraOptions.angle = (-direction * M_PI) / 180;
- }
- mbgl::AnimationOptions animationOptions;
- if (duration > 0) {
- animationOptions.duration.emplace(mbgl::Milliseconds(duration));
- // equivalent to kCAMediaTimingFunctionDefault in iOS
- animationOptions.easing.emplace(mbgl::util::UnitBezier { 0.25, 0.1, 0.25, 0.1 });
- }
-
- nativeMapView->getMap().easeTo(cameraOptions, animationOptions);
-}
-
-jni::jarray<jni::jobject>* nativeQueryRenderedFeaturesForPoint(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jfloat x, jni::jfloat y, jni::jarray<jni::jobject>* layerIds) {
- using namespace mbgl::android::conversion;
- using namespace mapbox::geometry;
-
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
-
- mbgl::optional<std::vector<std::string>> layers;
- if (layerIds != nullptr && jni::GetArrayLength(*env, *layerIds) > 0) {
- layers = toVector(*env, *layerIds);
- }
- point<double> point = {x, y};
-
- return *convert<jni::jarray<jni::jobject>*, std::vector<mbgl::Feature>>(*env, nativeMapView->getMap().queryRenderedFeatures(point, layers));
-}
-
-jni::jarray<jni::jobject>* nativeQueryRenderedFeaturesForBox(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jfloat left, jni::jfloat top, jni::jfloat right, jni::jfloat bottom, jni::jarray<jni::jobject>* layerIds) {
- using namespace mbgl::android::conversion;
- using namespace mapbox::geometry;
-
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
-
- mbgl::optional<std::vector<std::string>> layers;
- if (layerIds != nullptr && jni::GetArrayLength(*env, *layerIds) > 0) {
- layers = toVector(*env, *layerIds);
- }
- box<double> box = { point<double>{ left, top}, point<double>{ right, bottom } };
-
- return *convert<jni::jarray<jni::jobject>*, std::vector<mbgl::Feature>>(*env, nativeMapView->getMap().queryRenderedFeatures(box, layers));
-}
-
-void nativeOnLowMemory(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->getMap().onLowMemory();
-}
-
-void nativeSetDebug(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jboolean debug) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
-
- DebugOptions debugOptions = debug ? DebugOptions::TileBorders | DebugOptions::ParseStatus | DebugOptions::Collision
- : DebugOptions::NoDebug;
- nativeMapView->getMap().setDebug(debugOptions);
- nativeMapView->enableFps(debug);
-}
-
-void nativeToggleDebug(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->getMap().cycleDebugOptions();
- nativeMapView->enableFps(nativeMapView->getMap().getDebug() != DebugOptions::NoDebug);
-}
-
-jboolean nativeGetDebug(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- return nativeMapView->getMap().getDebug() != DebugOptions::NoDebug;
-}
-
-jboolean nativeIsFullyLoaded(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- return nativeMapView->getMap().isFullyLoaded();
-}
-
-void nativeSetReachability(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jboolean status) {
- assert(nativeMapViewPtr != 0);
- if (status) {
- mbgl::NetworkStatus::Reachable();
- }
-}
-
-jdouble nativeGetMetersPerPixelAtLatitude(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble lat, jdouble zoom) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- return nativeMapView->getMap().getMetersPerPixelAtLatitude(lat, zoom);
-}
-
-jni::jobject* nativeProjectedMetersForLatLng(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble latitude, jdouble longitude) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- mbgl::ProjectedMeters projectedMeters = nativeMapView->getMap().projectedMetersForLatLng(mbgl::LatLng(latitude, longitude));
- return &jni::NewObject(*env, *projectedMetersClass, *projectedMetersConstructorId, projectedMeters.northing, projectedMeters.easting);
-}
-
-jni::jobject* nativeLatLngForProjectedMeters(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble northing, jdouble easting) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- mbgl::LatLng latLng = nativeMapView->getMap().latLngForProjectedMeters(mbgl::ProjectedMeters(northing, easting));
- return &jni::NewObject(*env, *latLngClass, *latLngConstructorId, latLng.latitude, latLng.longitude);
-}
-
-jni::jobject* nativePixelForLatLng(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble latitude, jdouble longitude) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- mbgl::ScreenCoordinate pixel = nativeMapView->getMap().pixelForLatLng(mbgl::LatLng(latitude, longitude));
- return &jni::NewObject(*env, *pointFClass, *pointFConstructorId, static_cast<jfloat>(pixel.x), static_cast<jfloat>(pixel.y));
-}
-
-jni::jobject* nativeLatLngForPixel(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jfloat x, jfloat y) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- mbgl::LatLng latLng = nativeMapView->getMap().latLngForPixel(mbgl::ScreenCoordinate(x, y));
- return &jni::NewObject(*env, *latLngClass, *latLngConstructorId, latLng.latitude, latLng.longitude);
-}
-
-jdouble nativeGetTopOffsetPixelsForAnnotationSymbol(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* symbolName) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- return nativeMapView->getMap().getTopOffsetPixelsForAnnotationIcon(std_string_from_jstring(env, symbolName));
-}
-
-void nativeJumpTo(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble angle, jdouble latitude, jdouble longitude, jdouble pitch, jdouble zoom) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
-
- mbgl::CameraOptions options;
- if (angle != -1) {
- options.angle = (-angle * M_PI) / 180;
- }
- options.center = mbgl::LatLng(latitude, longitude);
- options.padding = nativeMapView->getInsets();
- if (pitch != -1) {
- options.pitch = pitch * M_PI / 180;
- }
- if (zoom != -1) {
- options.zoom = zoom;
- }
-
- nativeMapView->getMap().jumpTo(options);
-}
-
-void nativeEaseTo(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble angle, jdouble latitude, jdouble longitude, jlong duration, jdouble pitch, jdouble zoom, jboolean easing) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
-
- mbgl::CameraOptions cameraOptions;
- if (angle != -1) {
- cameraOptions.angle = (-angle * M_PI) / 180;
- }
- cameraOptions.center = mbgl::LatLng(latitude, longitude);
- cameraOptions.padding = nativeMapView->getInsets();
- if (pitch != -1) {
- cameraOptions.pitch = pitch * M_PI / 180;
- }
- if (zoom != -1) {
- cameraOptions.zoom = zoom;
- }
- mbgl::AnimationOptions animationOptions;
- animationOptions.duration.emplace(mbgl::Duration(duration));
-
- if (!easing) {
- // add a linear interpolator instead of easing
- animationOptions.easing.emplace(mbgl::util::UnitBezier { 0, 0, 1, 1 });
- }
-
- nativeMapView->getMap().easeTo(cameraOptions, animationOptions);
-}
-
-void nativeSetContentPadding(JNIEnv *env, jni::jobject* obj,long nativeMapViewPtr, double top, double left, double bottom, double right) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->setInsets({top, left, bottom, right});
-}
-
-void nativeFlyTo(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble angle, jdouble latitude, jdouble longitude, jlong duration, jdouble pitch, jdouble zoom) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
-
- mbgl::CameraOptions cameraOptions;
- if (angle != -1) {
- cameraOptions.angle = (-angle * M_PI) / 180 ;
- }
- cameraOptions.center = mbgl::LatLng(latitude, longitude);
- cameraOptions.padding = nativeMapView->getInsets();
- if (pitch != -1) {
- cameraOptions.pitch = pitch * M_PI / 180;
- }
- if (zoom != -1) {
- cameraOptions.zoom = zoom;
- }
- mbgl::AnimationOptions animationOptions;
- animationOptions.duration.emplace(mbgl::Duration(duration));
-
- nativeMapView->getMap().flyTo(cameraOptions, animationOptions);
-}
-
-jlong nativeGetTransitionDuration(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- assert(env);
- assert(nativeMapViewPtr != 0);
-
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
-
- const auto transitionOptions = nativeMapView->getMap().getTransitionOptions();
- return transitionOptions.duration.value_or(mbgl::Duration::zero()).count();
-}
-
-void nativeSetTransitionDuration(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jlong duration) {
- assert(env);
- assert(nativeMapViewPtr != 0);
-
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
-
- auto transitionOptions = nativeMapView->getMap().getTransitionOptions();
- transitionOptions.duration = std::chrono::duration_cast<mbgl::Duration>(std::chrono::duration<jlong>(duration));
- nativeMapView->getMap().setTransitionOptions(transitionOptions);
-}
-
-jlong nativeGetTransitionDelay(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- assert(env);
- assert(nativeMapViewPtr != 0);
-
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
-
- const auto transitionOptions = nativeMapView->getMap().getTransitionOptions();
- return transitionOptions.delay.value_or(mbgl::Duration::zero()).count();
-}
-
-void nativeSetTransitionDelay(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jlong delay) {
- assert(env);
- assert(nativeMapViewPtr != 0);
-
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
-
- auto transitionOptions = nativeMapView->getMap().getTransitionOptions();
- transitionOptions.delay = std::chrono::duration_cast<mbgl::Duration>(std::chrono::duration<jlong>(delay));
- nativeMapView->getMap().setTransitionOptions(transitionOptions);
-}
-
-jni::jobject* nativeGetLayer(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* layerId) {
- assert(env);
- assert(nativeMapViewPtr != 0);
-
- // Get the native map peer
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
-
- // Find the layer
- mbgl::style::Layer* coreLayer = nativeMapView->getMap().getLayer(std_string_from_jstring(env, layerId));
- if (!coreLayer) {
- mbgl::Log::Info(mbgl::Event::JNI, "No layer found");
- return jni::Object<Layer>();
- }
-
- // Create and return the layer's native peer
- return createJavaLayerPeer(*env, nativeMapView->getMap(), *coreLayer);
-}
-
-void nativeAddLayer(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jlong nativeLayerPtr, jni::jstring* before) {
- assert(nativeMapViewPtr != 0);
- assert(nativeLayerPtr != 0);
-
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
-
- Layer *layer = reinterpret_cast<Layer *>(nativeLayerPtr);
- try {
- layer->addToMap(nativeMapView->getMap(), before ? mbgl::optional<std::string>(std_string_from_jstring(env, before)) : mbgl::optional<std::string>());
- } catch (const std::runtime_error& error) {
- jni::ThrowNew(*env, jni::FindClass(*env, "com/mapbox/mapboxsdk/style/layers/CannotAddLayerException"), error.what());
- }
-}
-
-/**
- * Remove by layer id. Ownership is not transferred back
- */
-void nativeRemoveLayerById(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* id) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- try {
- nativeMapView->getMap().removeLayer(std_string_from_jstring(env, id));
- } catch (const std::runtime_error& error) {
- jni::ThrowNew(*env, jni::FindClass(*env, "com/mapbox/mapboxsdk/style/layers/NoSuchLayerException"), error.what());
- }
-}
-
-/**
- * Remove with wrapper object id. Ownership is transferred back to the wrapper
- */
-void nativeRemoveLayer(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jlong layerPtr) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- mbgl::android::Layer *layer = reinterpret_cast<mbgl::android::Layer *>(layerPtr);
- try {
- std::unique_ptr<mbgl::style::Layer> coreLayer = nativeMapView->getMap().removeLayer(layer->get().getID());
- layer->setLayer(std::move(coreLayer));
- } catch (const std::runtime_error& error) {
- jni::ThrowNew(*env, jni::FindClass(*env, "com/mapbox/mapboxsdk/style/layers/NoSuchLayerException"), error.what());
- }
-}
-
-
-jni::jobject* nativeGetSource(JNIEnv *env, jni::jobject* obj, jni::jlong nativeMapViewPtr, jni::jstring* sourceId) {
- assert(env);
- assert(nativeMapViewPtr != 0);
-
- // Get the native map peer
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
-
- // Find the source
- mbgl::style::Source* coreSource = nativeMapView->getMap().getSource(std_string_from_jstring(env, sourceId));
- if (!coreSource) {
- mbgl::Log::Info(mbgl::Event::JNI, "No source found");
- return jni::Object<Source>();
- }
-
- // Create and return the source's native peer
- return createJavaSourcePeer(*env, nativeMapView->getMap(), *coreSource);
-}
-
-void nativeAddSource(JNIEnv *env, jni::jobject* obj, jni::jlong nativeMapViewPtr, jni::jlong nativeSourcePtr) {
- assert(nativeMapViewPtr != 0);
- assert(nativeSourcePtr != 0);
-
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
-
- Source *source = reinterpret_cast<Source *>(nativeSourcePtr);
- try {
- source->addToMap(nativeMapView->getMap());
- } catch (const std::runtime_error& error) {
- jni::ThrowNew(*env, jni::FindClass(*env, "com/mapbox/mapboxsdk/style/sources/CannotAddSourceException"), error.what());
- }
-}
-
-void nativeRemoveSourceById(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* id) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- try {
- nativeMapView->getMap().removeSource(std_string_from_jstring(env, id));
- } catch (const std::runtime_error& error) {
- jni::ThrowNew(*env, jni::FindClass(*env, "com/mapbox/mapboxsdk/style/sources/NoSuchSourceException"), error.what());
- }
-}
-
-void nativeRemoveSource(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jlong sourcePtr) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- mbgl::android::Source *source = reinterpret_cast<mbgl::android::Source *>(sourcePtr);
- try {
- std::unique_ptr<mbgl::style::Source> coreSource = nativeMapView->getMap().removeSource(source->get().getID());
- source->setSource(std::move(coreSource));
- } catch (const std::runtime_error& error) {
- jni::ThrowNew(*env, jni::FindClass(*env, "com/mapbox/mapboxsdk/style/sources/NoSuchSourceException"), error.what());
- }
-}
-
-void nativeAddImage(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* name, jni::jint width, jni::jint height, jni::jfloat pixelRatio, jni::jarray<jbyte>* data) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
-
- // Create Pre-multiplied image from byte[]
- NullCheck(*env, data);
- std::size_t size = jni::GetArrayLength(*env, *data);
- mbgl::PremultipliedImage premultipliedImage(
- { static_cast<uint32_t>(width), static_cast<uint32_t>(height) });
-
- if (premultipliedImage.bytes() != uint32_t(size)) {
- throw mbgl::util::SpriteImageException("Sprite image pixel count mismatch");
- }
-
- jni::GetArrayRegion(*env, *data, 0, size, reinterpret_cast<jbyte*>(premultipliedImage.data.get()));
-
- // Wrap in a SpriteImage with the correct pixel ratio
- auto spriteImage = std::make_unique<mbgl::SpriteImage>(std::move(premultipliedImage), float(pixelRatio));
-
- nativeMapView->getMap().addImage(std_string_from_jstring(env, name), std::move(spriteImage));
-}
-
-void nativeRemoveImage(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* name) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->getMap().removeImage(std_string_from_jstring(env, name));
-}
-
-void nativeScheduleTakeSnapshot(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->scheduleTakeSnapshot();
-}
-
// Offline calls begin
jlong createDefaultFileSource(JNIEnv *env, jni::jobject* obj, jni::jstring* cachePath_, jni::jstring* assetRoot_, jlong maximumCacheSize) {
@@ -1731,11 +709,33 @@ void registerNatives(JavaVM *vm) {
//For the DefaultFileSource
static mbgl::util::RunLoop mainRunLoop;
- mbgl::android::RegisterNativeHTTPRequest(env);
-
+ //Basic types
java::registerNatives(env);
+ java::util::registerNative(env);
+ PointF::registerNative(env);
+ RectF::registerNative(env);
+
+ //Geometry
+ Feature::registerNative(env);
+ LatLng::registerNative(env);
+ ProjectedMeters::registerNative(env);
+
+ //Annotation
+ Marker::registerNative(env);
+ Polygon::registerNative(env);
+ Polyline::registerNative(env);
+
+ //Map
+ NativeMapView::registerNative(env);
+
+ //Http
+ RegisterNativeHTTPRequest(env);
+
+ //Bitmap
Bitmap::registerNative(env);
BitmapFactory::registerNative(env);
+
+ //Style
registerNativeLayers(env);
registerNativeSources(env);
Stop::registerNative(env);
@@ -1743,13 +743,9 @@ void registerNatives(JavaVM *vm) {
ExponentialStops::registerNative(env);
IdentityStops::registerNative(env);
IntervalStops::registerNative(env);
- ConnectivityListener::registerNative(env);
- latLngClass = &jni::FindClass(env, "com/mapbox/mapboxsdk/geometry/LatLng");
- latLngClass = jni::NewGlobalRef(env, latLngClass).release();
- latLngConstructorId = &jni::GetMethodID(env, *latLngClass, "<init>", "(DD)V");
- latLngLatitudeId = &jni::GetFieldID(env, *latLngClass, "latitude", "D");
- latLngLongitudeId = &jni::GetFieldID(env, *latLngClass, "longitude", "D");
+ //Connectivity
+ ConnectivityListener::registerNative(env);
latLngBoundsClass = &jni::FindClass(env, "com/mapbox/mapboxsdk/geometry/LatLngBounds");
latLngBoundsClass = jni::NewGlobalRef(env, latLngBoundsClass).release();
@@ -1759,156 +755,6 @@ void registerNatives(JavaVM *vm) {
latLngBoundsLonEastId = &jni::GetFieldID(env, *latLngBoundsClass, "mLonEast", "D");
latLngBoundsLonWestId = &jni::GetFieldID(env, *latLngBoundsClass, "mLonWest", "D");
- iconClass = &jni::FindClass(env, "com/mapbox/mapboxsdk/annotations/Icon");
- iconClass = jni::NewGlobalRef(env, iconClass).release();
- iconIdId = &jni::GetFieldID(env, *iconClass, "mId", "Ljava/lang/String;");
-
- markerClass = &jni::FindClass(env, "com/mapbox/mapboxsdk/annotations/Marker");
- markerClass = jni::NewGlobalRef(env, markerClass).release();
- markerPositionId = &jni::GetFieldID(env, *markerClass, "position", "Lcom/mapbox/mapboxsdk/geometry/LatLng;");
- markerIconId = &jni::GetFieldID(env, *markerClass, "icon", "Lcom/mapbox/mapboxsdk/annotations/Icon;");
- markerIdId = &jni::GetFieldID(env, *markerClass, "id", "J");
-
- polylineClass = &jni::FindClass(env, "com/mapbox/mapboxsdk/annotations/Polyline");
- polylineClass = jni::NewGlobalRef(env, polylineClass).release();
- polylineAlphaId = &jni::GetFieldID(env, *polylineClass, "alpha", "F");
- polylineColorId = &jni::GetFieldID(env, *polylineClass, "color", "I");
- polylineWidthId = &jni::GetFieldID(env, *polylineClass, "width", "F");
- polylinePointsId = &jni::GetFieldID(env, *polylineClass, "points", "Ljava/util/List;");
-
- polygonClass = &jni::FindClass(env, "com/mapbox/mapboxsdk/annotations/Polygon");
- polygonClass = jni::NewGlobalRef(env, polygonClass).release();
- polygonAlphaId = &jni::GetFieldID(env, *polygonClass, "alpha", "F");
- polygonFillColorId = &jni::GetFieldID(env, *polygonClass, "fillColor", "I");
- polygonStrokeColorId = &jni::GetFieldID(env, *polygonClass, "strokeColor", "I");
- polygonPointsId = &jni::GetFieldID(env, *polygonClass, "points", "Ljava/util/List;");
-
- jni::jclass* listClass = &jni::FindClass(env, "java/util/List");
- listToArrayId = &jni::GetMethodID(env, *listClass, "toArray", "()[Ljava/lang/Object;");
-
- arrayListClass = &jni::FindClass(env, "java/util/ArrayList");
- arrayListClass = jni::NewGlobalRef(env, arrayListClass).release();
- arrayListConstructorId = &jni::GetMethodID(env, *arrayListClass, "<init>", "()V");
- arrayListAddId = &jni::GetMethodID(env, *arrayListClass, "add", "(Ljava/lang/Object;)Z");
-
- projectedMetersClass = &jni::FindClass(env, "com/mapbox/mapboxsdk/geometry/ProjectedMeters");
- projectedMetersClass = jni::NewGlobalRef(env, projectedMetersClass).release();
- projectedMetersConstructorId = &jni::GetMethodID(env, *projectedMetersClass, "<init>", "(DD)V");
- projectedMetersNorthingId = &jni::GetFieldID(env, *projectedMetersClass, "northing", "D");
- projectedMetersEastingId = &jni::GetFieldID(env, *projectedMetersClass, "easting", "D");
-
- pointFClass = &jni::FindClass(env, "android/graphics/PointF");
- pointFClass = jni::NewGlobalRef(env, pointFClass).release();
- pointFConstructorId = &jni::GetMethodID(env, *pointFClass, "<init>", "(FF)V");
- pointFXId = &jni::GetFieldID(env, *pointFClass, "x", "F");
- pointFYId = &jni::GetFieldID(env, *pointFClass, "y", "F");
-
- rectFClass = &jni::FindClass(env, "android/graphics/RectF");
- rectFClass = jni::NewGlobalRef(env, rectFClass).release();
- rectFConstructorId = &jni::GetMethodID(env, *rectFClass, "<init>", "()V");
- rectFLeftId = &jni::GetFieldID(env, *rectFClass, "left", "F");
- rectFRightId = &jni::GetFieldID(env, *rectFClass, "right", "F");
- rectFTopId = &jni::GetFieldID(env, *rectFClass, "top", "F");
- rectFBottomId = &jni::GetFieldID(env, *rectFClass, "bottom", "F");
-
- jni::jclass& nativeMapViewClass = jni::FindClass(env, "com/mapbox/mapboxsdk/maps/NativeMapView");
-
- onInvalidateId = &jni::GetMethodID(env, nativeMapViewClass, "onInvalidate", "()V");
- wakeCallbackId = &jni::GetMethodID(env, nativeMapViewClass, "wakeCallback","()V");
- onMapChangedId = &jni::GetMethodID(env, nativeMapViewClass, "onMapChanged", "(I)V");
- onFpsChangedId = &jni::GetMethodID(env, nativeMapViewClass, "onFpsChanged", "(D)V");
- onSnapshotReadyId = &jni::GetMethodID(env, nativeMapViewClass, "onSnapshotReady","(Landroid/graphics/Bitmap;)V");
-
- #define MAKE_NATIVE_METHOD(name, sig) jni::MakeNativeMethod<decltype(name), name>( #name, sig )
-
- jni::RegisterNatives(env, nativeMapViewClass,
- MAKE_NATIVE_METHOD(nativeCreate, "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;FIJ)J"),
- MAKE_NATIVE_METHOD(nativeDestroy, "(J)V"),
- MAKE_NATIVE_METHOD(nativeUpdate, "(J)V"),
- MAKE_NATIVE_METHOD(nativeRender, "(J)V"),
- MAKE_NATIVE_METHOD(nativeOnViewportChanged, "(JII)V"),
- MAKE_NATIVE_METHOD(nativeAddClass, "(JLjava/lang/String;)V"),
- MAKE_NATIVE_METHOD(nativeRemoveClass, "(JLjava/lang/String;)V"),
- MAKE_NATIVE_METHOD(nativeHasClass, "(JLjava/lang/String;)Z"),
- MAKE_NATIVE_METHOD(nativeSetClasses, "(JLjava/util/List;)V"),
- MAKE_NATIVE_METHOD(nativeGetClasses, "(J)Ljava/util/List;"),
- MAKE_NATIVE_METHOD(nativeSetStyleUrl, "(JLjava/lang/String;)V"),
- MAKE_NATIVE_METHOD(nativeGetStyleUrl, "(J)Ljava/lang/String;"),
- MAKE_NATIVE_METHOD(nativeSetStyleJson, "(JLjava/lang/String;)V"),
- MAKE_NATIVE_METHOD(nativeGetStyleJson, "(J)Ljava/lang/String;"),
- MAKE_NATIVE_METHOD(nativeSetAccessToken, "(JLjava/lang/String;)V"),
- MAKE_NATIVE_METHOD(nativeGetAccessToken, "(J)Ljava/lang/String;"),
- MAKE_NATIVE_METHOD(nativeCancelTransitions, "(J)V"),
- MAKE_NATIVE_METHOD(nativeSetGestureInProgress, "(JZ)V"),
- MAKE_NATIVE_METHOD(nativeMoveBy, "(JDDJ)V"),
- MAKE_NATIVE_METHOD(nativeSetLatLng, "(JDDJ)V"),
- MAKE_NATIVE_METHOD(nativeGetLatLng, "(J)Lcom/mapbox/mapboxsdk/geometry/LatLng;"),
- MAKE_NATIVE_METHOD(nativeResetPosition, "(J)V"),
- MAKE_NATIVE_METHOD(nativeGetCameraValues, "(J)[D"),
- MAKE_NATIVE_METHOD(nativeGetPitch, "(J)D"),
- MAKE_NATIVE_METHOD(nativeSetPitch, "(JDJ)V"),
- MAKE_NATIVE_METHOD(nativeScaleBy, "(JDDDJ)V"),
- MAKE_NATIVE_METHOD(nativeSetScale, "(JDDDJ)V"),
- MAKE_NATIVE_METHOD(nativeGetScale, "(J)D"),
- MAKE_NATIVE_METHOD(nativeSetZoom, "(JDJ)V"),
- MAKE_NATIVE_METHOD(nativeGetZoom, "(J)D"),
- MAKE_NATIVE_METHOD(nativeResetZoom, "(J)V"),
- MAKE_NATIVE_METHOD(nativeGetMinZoom, "(J)D"),
- MAKE_NATIVE_METHOD(nativeSetMinZoom, "(JD)V"),
- MAKE_NATIVE_METHOD(nativeGetMaxZoom, "(J)D"),
- MAKE_NATIVE_METHOD(nativeSetMaxZoom, "(JD)V"),
- MAKE_NATIVE_METHOD(nativeRotateBy, "(JDDDDJ)V"),
- MAKE_NATIVE_METHOD(nativeSetBearing, "(JDJ)V"),
- MAKE_NATIVE_METHOD(nativeSetFocalBearing, "(JDDDJ)V"),
- MAKE_NATIVE_METHOD(nativeSetBearingXY, "(JDDD)V"),
- MAKE_NATIVE_METHOD(nativeGetBearing, "(J)D"),
- MAKE_NATIVE_METHOD(nativeResetNorth, "(J)V"),
- MAKE_NATIVE_METHOD(nativeAddMarkers, "(J[Lcom/mapbox/mapboxsdk/annotations/Marker;)[J"),
- MAKE_NATIVE_METHOD(nativeAddPolylines, "(J[Lcom/mapbox/mapboxsdk/annotations/Polyline;)[J"),
- MAKE_NATIVE_METHOD(nativeAddPolygons, "(J[Lcom/mapbox/mapboxsdk/annotations/Polygon;)[J"),
- MAKE_NATIVE_METHOD(nativeUpdateMarker, "(JJDDLjava/lang/String;)V"),
- MAKE_NATIVE_METHOD(nativeUpdatePolygon, "(JJLcom/mapbox/mapboxsdk/annotations/Polygon;)V"),
- MAKE_NATIVE_METHOD(nativeUpdatePolyline, "(JJLcom/mapbox/mapboxsdk/annotations/Polyline;)V"),
- MAKE_NATIVE_METHOD(nativeRemoveAnnotations, "(J[J)V"),
- MAKE_NATIVE_METHOD(nativeQueryPointAnnotations, "(JLandroid/graphics/RectF;)[J"),
- MAKE_NATIVE_METHOD(nativeAddAnnotationIcon, "(JLjava/lang/String;IIF[B)V"),
- MAKE_NATIVE_METHOD(nativeSetVisibleCoordinateBounds, "(J[Lcom/mapbox/mapboxsdk/geometry/LatLng;Landroid/graphics/RectF;DJ)V"),
- MAKE_NATIVE_METHOD(nativeOnLowMemory, "(J)V"),
- MAKE_NATIVE_METHOD(nativeSetDebug, "(JZ)V"),
- MAKE_NATIVE_METHOD(nativeToggleDebug, "(J)V"),
- MAKE_NATIVE_METHOD(nativeGetDebug, "(J)Z"),
- MAKE_NATIVE_METHOD(nativeIsFullyLoaded, "(J)Z"),
- MAKE_NATIVE_METHOD(nativeSetReachability, "(JZ)V"),
- MAKE_NATIVE_METHOD(nativeGetMetersPerPixelAtLatitude, "(JDD)D"),
- MAKE_NATIVE_METHOD(nativeProjectedMetersForLatLng, "(JDD)Lcom/mapbox/mapboxsdk/geometry/ProjectedMeters;"),
- MAKE_NATIVE_METHOD(nativeLatLngForProjectedMeters, "(JDD)Lcom/mapbox/mapboxsdk/geometry/LatLng;"),
- MAKE_NATIVE_METHOD(nativePixelForLatLng, "(JDD)Landroid/graphics/PointF;"),
- MAKE_NATIVE_METHOD(nativeLatLngForPixel, "(JFF)Lcom/mapbox/mapboxsdk/geometry/LatLng;"),
- MAKE_NATIVE_METHOD(nativeGetTopOffsetPixelsForAnnotationSymbol, "(JLjava/lang/String;)D"),
- MAKE_NATIVE_METHOD(nativeJumpTo, "(JDDDDD)V"),
- MAKE_NATIVE_METHOD(nativeEaseTo, "(JDDDJDDZ)V"),
- MAKE_NATIVE_METHOD(nativeFlyTo, "(JDDDJDD)V"),
- MAKE_NATIVE_METHOD(nativeGetTransitionDuration, "(J)J"),
- MAKE_NATIVE_METHOD(nativeSetTransitionDuration, "(JJ)V"),
- MAKE_NATIVE_METHOD(nativeGetTransitionDelay, "(J)J"),
- MAKE_NATIVE_METHOD(nativeSetTransitionDelay, "(JJ)V"),
- MAKE_NATIVE_METHOD(nativeGetLayer, "(JLjava/lang/String;)Lcom/mapbox/mapboxsdk/style/layers/Layer;"),
- MAKE_NATIVE_METHOD(nativeAddLayer, "(JJLjava/lang/String;)V"),
- MAKE_NATIVE_METHOD(nativeRemoveLayerById, "(JLjava/lang/String;)V"),
- MAKE_NATIVE_METHOD(nativeRemoveLayer, "(JJ)V"),
- MAKE_NATIVE_METHOD(nativeGetSource, "(JLjava/lang/String;)Lcom/mapbox/mapboxsdk/style/sources/Source;"),
- MAKE_NATIVE_METHOD(nativeAddSource, "(JJ)V"),
- MAKE_NATIVE_METHOD(nativeRemoveSourceById, "(JLjava/lang/String;)V"),
- MAKE_NATIVE_METHOD(nativeRemoveSource, "(JJ)V"),
- MAKE_NATIVE_METHOD(nativeAddImage, "(JLjava/lang/String;IIF[B)V"),
- MAKE_NATIVE_METHOD(nativeRemoveImage, "(JLjava/lang/String;)V"),
- MAKE_NATIVE_METHOD(nativeSetContentPadding, "(JDDDD)V"),
- MAKE_NATIVE_METHOD(nativeScheduleTakeSnapshot, "(J)V"),
- MAKE_NATIVE_METHOD(nativeQueryRenderedFeaturesForPoint, "(JFF[Ljava/lang/String;)[Lcom/mapbox/services/commons/geojson/Feature;"),
- MAKE_NATIVE_METHOD(nativeQueryRenderedFeaturesForBox, "(JFFFF[Ljava/lang/String;)[Lcom/mapbox/services/commons/geojson/Feature;"),
- MAKE_NATIVE_METHOD(nativeSetAPIBaseURL, "(JLjava/lang/String;)V")
- );
-
// Offline begin
struct OfflineManager {
@@ -1930,6 +776,8 @@ void registerNatives(JavaVM *vm) {
jni::Class<OfflineManager> offlineManagerClass = jni::Class<OfflineManager>::Find(env);
offlineManagerClassPtrId = &jni::GetFieldID(env, offlineManagerClass, "mDefaultFileSourcePtr", "J");
+ #define MAKE_NATIVE_METHOD(name, sig) jni::MakeNativeMethod<decltype(name), name>( #name, sig )
+
jni::RegisterNatives(env, offlineManagerClass,
MAKE_NATIVE_METHOD(createDefaultFileSource, "(Ljava/lang/String;Ljava/lang/String;J)J"),
MAKE_NATIVE_METHOD(setAccessToken, "(JLjava/lang/String;)V"),
diff --git a/platform/android/src/jni.hpp b/platform/android/src/jni.hpp
index 04bad003f6..4b55173926 100644
--- a/platform/android/src/jni.hpp
+++ b/platform/android/src/jni.hpp
@@ -1,6 +1,7 @@
#pragma once
#include <string>
+#include <jni/jni.hpp>
typedef struct _jmethodID* jmethodID;
typedef struct _JavaVM JavaVM;
@@ -16,16 +17,13 @@ extern std::string dataPath;
extern std::string apkPath;
extern std::string androidRelease;
-extern jmethodID onInvalidateId;
-extern jmethodID wakeCallbackId;
-extern jmethodID onMapChangedId;
-extern jmethodID onFpsChangedId;
-extern jmethodID onSnapshotReadyId;
-
-extern bool attach_jni_thread(JavaVM* vm, JNIEnv** env, std::string threadName);
-extern void detach_jni_thread(JavaVM* vm, JNIEnv** env, bool detach);
+bool attach_jni_thread(JavaVM* vm, JNIEnv** env, std::string threadName);
+void detach_jni_thread(JavaVM* vm, JNIEnv** env, bool detach);
extern void registerNatives(JavaVM* vm);
+template<typename F>
+void attachThreadAndExecute(F&& function);
+
} // namespace android
} // namespace mbgl
diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp
index 50fa8944f7..484e14b111 100755
--- a/platform/android/src/native_map_view.cpp
+++ b/platform/android/src/native_map_view.cpp
@@ -1,6 +1,4 @@
#include "native_map_view.hpp"
-#include "jni.hpp"
-#include <jni/jni.hpp>
#include <cstdlib>
#include <ctime>
@@ -11,130 +9,149 @@
#include <sys/system_properties.h>
-#include <mbgl/util/platform.hpp>
-#include <mbgl/util/event.hpp>
-#include <mbgl/util/logging.hpp>
-#include <mbgl/gl/extension.hpp>
+#include <EGL/egl.h>
+
+#include <jni/jni.hpp>
+
#include <mbgl/gl/context.hpp>
+#include <mbgl/gl/extension.hpp>
#include <mbgl/util/constants.hpp>
+#include <mbgl/util/event.hpp>
+#include <mbgl/util/exception.hpp>
+#include <mbgl/util/geo.hpp>
#include <mbgl/util/image.hpp>
+#include <mbgl/util/logging.hpp>
+#include <mbgl/util/platform.hpp>
+#include <mbgl/sprite/sprite_image.hpp>
+#include "conversion/conversion.hpp"
+#include "conversion/collection.hpp"
+#include "geometry/conversion/feature.hpp"
+
+#include "jni.hpp"
+#include "attach_env.hpp"
#include "bitmap.hpp"
#include "run_loop_impl.hpp"
+#include "java/util.hpp"
namespace mbgl {
namespace android {
-NativeMapView::NativeMapView(JNIEnv *env_, jobject obj_, float _pixelRatio, int availableProcessors_, size_t totalMemory_)
- : env(env_),
- pixelRatio(_pixelRatio),
- availableProcessors(availableProcessors_),
- totalMemory(totalMemory_),
- runLoop(std::make_unique<mbgl::util::RunLoop>(mbgl::util::RunLoop::Type::New)),
- threadPool(4) {
+using DebugOptions = mbgl::MapDebugOptions;
+
+NativeMapView::NativeMapView(jni::JNIEnv& _env, jni::Object<NativeMapView> _obj, jni::String _cachePath, jni::String _apkPath,
+ jni::jfloat _pixelRatio, jni::jint _availableProcessors, jni::jlong _totalMemory) :
+ javaPeer(_obj.NewWeakGlobalRef(_env)),
+ pixelRatio(_pixelRatio),
+ availableProcessors(_availableProcessors),
+ totalMemory(_totalMemory),
+ runLoop(std::make_unique<mbgl::util::RunLoop>(mbgl::util::RunLoop::Type::New)),
+ threadPool(4) {
+
mbgl::Log::Info(mbgl::Event::Android, "NativeMapView::NativeMapView");
//Add a wake function to wake the render thread when needed
mbgl::util::RunLoop::Impl* loop = reinterpret_cast<mbgl::util::RunLoop::Impl*>(mbgl::util::RunLoop::getLoopHandle());
loop->setWakeFunction(std::bind(&NativeMapView::wake, this));
- assert(env_ != nullptr);
- assert(obj_ != nullptr);
-
- if (env->GetJavaVM(&vm) < 0) {
- env->ExceptionDescribe();
- return;
- }
-
- obj = env->NewWeakGlobalRef(obj_);
- if (obj == nullptr) {
- env->ExceptionDescribe();
+ // Get a reference to the JavaVM for callbacks
+ //TODO: Why?
+ if (_env.GetJavaVM(&vm) < 0) {
+ _env.ExceptionDescribe();
return;
}
+ // Create a default file source for this map instance
fileSource = std::make_unique<mbgl::DefaultFileSource>(
- mbgl::android::cachePath + "/mbgl-offline.db",
- mbgl::android::apkPath);
+ jni::Make<std::string>(_env, _cachePath) + "/mbgl-offline.db",
+ jni::Make<std::string>(_env, _apkPath));
+ // Create the core map
map = std::make_unique<mbgl::Map>(
*this, mbgl::Size{ static_cast<uint32_t>(width), static_cast<uint32_t>(height) },
pixelRatio, *fileSource, threadPool, MapMode::Continuous);
+ //Calculate a fitting cache size based on device parameters
float zoomFactor = map->getMaxZoom() - map->getMinZoom() + 1;
float cpuFactor = availableProcessors;
float memoryFactor = static_cast<float>(totalMemory) / 1000.0f / 1000.0f / 1000.0f;
float sizeFactor = (static_cast<float>(map->getSize().width) / mbgl::util::tileSize) *
- (static_cast<float>(map->getSize().height) / mbgl::util::tileSize);
-
- size_t cacheSize = zoomFactor * cpuFactor * memoryFactor * sizeFactor * 0.5f;
+ (static_cast<float>(map->getSize().height) / mbgl::util::tileSize);
- map->setSourceTileCacheSize(cacheSize);
+ map->setSourceTileCacheSize(zoomFactor * cpuFactor * memoryFactor * sizeFactor * 0.5f);
}
+/**
+ * Called through NativeMapView#destroy()
+ */
NativeMapView::~NativeMapView() {
mbgl::Log::Info(mbgl::Event::Android, "NativeMapView::~NativeMapView");
- assert(vm != nullptr);
- assert(obj != nullptr);
+ //Remove the wake function as the JVM object is going to be GC'd pretty soon
+ mbgl::util::RunLoop::Impl* loop = reinterpret_cast<mbgl::util::RunLoop::Impl*>(mbgl::util::RunLoop::getLoopHandle());
+ loop->setWakeFunction(nullptr);
map.reset();
fileSource.reset();
- env->DeleteWeakGlobalRef(obj);
-
- obj = nullptr;
- env = nullptr;
vm = nullptr;
}
-mbgl::Size NativeMapView::getFramebufferSize() const {
- mbgl::Log::Info(mbgl::Event::Android, "FB size %dx%d", fbWidth, fbHeight);
- return { static_cast<uint32_t>(fbWidth), static_cast<uint32_t>(fbHeight) };
-}
-
-void NativeMapView::wake() {
- mbgl::Log::Info(mbgl::Event::JNI, "Wake callback");
-
- JNIEnv *env2;
- jboolean detach = attach_jni_thread(theJVM, &env2, "GL Callback Thread");
- if (!detach) {
- env2->CallVoidMethod(obj, wakeCallbackId);
- if (env2->ExceptionCheck()) {
- env2->ExceptionDescribe();
- }
- }
- detach_jni_thread(theJVM, &env2, detach);
-}
-
-void NativeMapView::updateViewBinding() {
- getContext().bindFramebuffer.setCurrentValue(0);
- assert(mbgl::gl::value::BindFramebuffer::Get() == getContext().bindFramebuffer.getCurrentValue());
- getContext().viewport.setCurrentValue({ 0, 0, getFramebufferSize() });
- assert(mbgl::gl::value::Viewport::Get() == getContext().viewport.getCurrentValue());
-}
-
+/**
+ * From mbgl::View
+ */
void NativeMapView::bind() {
getContext().bindFramebuffer = 0;
getContext().viewport = { 0, 0, getFramebufferSize() };
}
+/**
+ * From mbgl::Backend. Callback to java NativeMapView#onInvalidate().
+ *
+ * May be called from any thread
+ */
void NativeMapView::invalidate() {
Log::Info(mbgl::Event::Android, "NativeMapView::invalidate");
+ android::UniqueEnv _env = android::AttachEnv();
+ static auto onInvalidate = javaClass.GetMethod<void ()>(*_env, "onInvalidate");
+ javaPeer->Call(*_env, onInvalidate);
+}
+
+/**
+ * From mbgl::Backend. Callback to java NativeMapView#onMapChanged(int).
+ *
+ * May be called from any thread
+ */
+void NativeMapView::notifyMapChange(mbgl::MapChange change) {
+ mbgl::Log::Info(mbgl::Event::Android, "notifyMapChange");
assert(vm != nullptr);
- assert(obj != nullptr);
- JNIEnv *env2;
- jboolean renderDetach = attach_jni_thread(theJVM, &env2, "Callback Thread");
- if (!renderDetach) {
- env2->CallVoidMethod(obj, onInvalidateId);
- if(env2->ExceptionCheck()) {
- env2->ExceptionDescribe();
- }
- }
+
+ android::UniqueEnv _env = android::AttachEnv();
+ static auto onMapChanged = javaClass.GetMethod<void (int)>(*_env, "onMapChanged");
+ javaPeer->Call(*_env, onMapChanged, (int) change);
+}
+
+// JNI Methods //
+
+void NativeMapView::onViewportChanged(jni::JNIEnv&, jni::jint w, jni::jint h) {
+ resizeView((int) w / pixelRatio, (int) h / pixelRatio);
+ resizeFramebuffer(w, h);
}
-void NativeMapView::render() {
+void NativeMapView::render(jni::JNIEnv& env) {
mbgl::Log::Info(mbgl::Event::Android, "NativeMapView::render");
+ if (firstRender) {
+ mbgl::Log::Info(mbgl::Event::Android, "Initialize GL extensions");
+ mbgl::gl::InitializeExtensions([] (const char * name) {
+ return reinterpret_cast<mbgl::gl::glProc>(eglGetProcAddress(name));
+ });
+ firstRender = false;
+ }
+
+ //First, spin the run loop to process the queue (as there is no actual loop on the render thread)
+ mbgl::util::RunLoop::Get()->runOnce();
+
if (framebufferSizeChanged) {
getContext().viewport = { 0, 0, getFramebufferSize() };
framebufferSizeChanged = false;
@@ -148,85 +165,576 @@ void NativeMapView::render() {
// take snapshot
auto image = getContext().readFramebuffer<mbgl::PremultipliedImage>(getFramebufferSize());
- auto bitmap = Bitmap::CreateBitmap(*env, std::move(image));
-
- JNIEnv *env2;
- jboolean renderDetach = attach_jni_thread(theJVM, &env2, "Callback Thread");
- if (!renderDetach) {
- env2->CallVoidMethod(obj, onSnapshotReadyId, jni::Unwrap(*bitmap));
- if (env2->ExceptionCheck()) {
- env2->ExceptionDescribe();
- }
- }
+ auto bitmap = Bitmap::CreateBitmap(env, std::move(image));
+
+ android::UniqueEnv _env = android::AttachEnv();
+ static auto onSnapshotReady = javaClass.GetMethod<void (jni::Object<Bitmap>)>(*_env, "onSnapshotReady");
+ javaPeer->Call(*_env, onSnapshotReady, bitmap);
}
updateFps();
}
-mbgl::Map &NativeMapView::getMap() { return *map; }
+void NativeMapView::setAPIBaseUrl(jni::JNIEnv& env, jni::String url) {
+ fileSource->setAPIBaseURL(jni::Make<std::string>(env, url));
+}
-mbgl::DefaultFileSource &NativeMapView::getFileSource() { return *fileSource; }
+jni::String NativeMapView::getStyleUrl(jni::JNIEnv& env) {
+ return jni::Make<jni::String>(env, map->getStyleURL());
+}
-void NativeMapView::scheduleTakeSnapshot() {
- snapshot = true;
+void NativeMapView::setStyleUrl(jni::JNIEnv& env, jni::String url) {
+ map->setStyleURL(jni::Make<std::string>(env, url));
}
+jni::String NativeMapView::getStyleJson(jni::JNIEnv& env) {
+ return jni::Make<jni::String>(env, map->getStyleJSON());
+}
-void NativeMapView::notifyMapChange(mbgl::MapChange change) {
- mbgl::Log::Info(mbgl::Event::Android, "notifyMapChange");
- assert(vm != nullptr);
- assert(obj != nullptr);
-
- JNIEnv *env2;
- jboolean renderDetach = attach_jni_thread(theJVM, &env2, "Callback Thread");
- if (!renderDetach) {
- env2->CallVoidMethod(obj, onMapChangedId, change);
- if(env2->ExceptionCheck()) {
- env2->ExceptionDescribe();
- }
+void NativeMapView::setStyleJson(jni::JNIEnv& env, jni::String json) {
+ map->setStyleJSON(jni::Make<std::string>(env, json));
+}
+
+jni::String NativeMapView::getAccessToken(jni::JNIEnv& env) {
+ return jni::Make<jni::String>(env, fileSource->getAccessToken());
+}
+
+void NativeMapView::setAccessToken(jni::JNIEnv& env, jni::String token) {
+ fileSource->setAccessToken(jni::Make<std::string>(env, token));
+}
+
+void NativeMapView::cancelTransitions(jni::JNIEnv&) {
+ map->cancelTransitions();
+}
+
+void NativeMapView::setGestureInProgress(jni::JNIEnv&, jni::jboolean inProgress) {
+ map->setGestureInProgress(inProgress);
+}
+
+void NativeMapView::moveBy(jni::JNIEnv&, jni::jdouble dx, jni::jdouble dy) {
+ map->moveBy({dx, dy});
+}
+
+jni::Object<LatLng> NativeMapView::getLatLng(JNIEnv& env) {
+ mbgl::LatLng latLng = map->getLatLng(insets);
+ return LatLng::New(env, latLng.latitude, latLng.longitude);
+}
+
+void NativeMapView::setLatLng(jni::JNIEnv&, jni::jdouble latitude, jni::jdouble longitude) {
+ map->setLatLng(mbgl::LatLng(latitude, longitude), insets);
+}
+
+void NativeMapView::setReachability(jni::JNIEnv&, jni::jboolean reachable) {
+ if (reachable) {
+ mbgl::NetworkStatus::Reachable();
}
}
-void NativeMapView::enableFps(bool enable) {
+void NativeMapView::resetPosition(jni::JNIEnv&) {
+ map->resetPosition();
+}
+
+jni::jdouble NativeMapView::getPitch(jni::JNIEnv&) {
+ return map->getPitch();
+}
+
+void NativeMapView::setPitch(jni::JNIEnv&, jni::jdouble pitch) {
+ map->setPitch(pitch);
+}
+
+void NativeMapView::scaleBy(jni::JNIEnv&, jni::jdouble ds, jni::jdouble cx, jni::jdouble cy) {
+ mbgl::ScreenCoordinate center(cx, cy);
+ map->scaleBy(ds, center);
+}
+
+void NativeMapView::setScale(jni::JNIEnv&, jni::jdouble scale, jni::jdouble cx, jni::jdouble cy) {
+ mbgl::ScreenCoordinate center(cx, cy);
+ map->setScale(scale, center);
+}
+
+jni::jdouble NativeMapView::getScale(jni::JNIEnv&) {
+ return map->getScale();
+}
+
+void NativeMapView::setZoom(jni::JNIEnv&, jni::jdouble zoom) {
+ map->setZoom(zoom);
+}
+
+jni::jdouble NativeMapView::getZoom(jni::JNIEnv&) {
+ return map->getZoom();
+}
+
+void NativeMapView::resetZoom(jni::JNIEnv&) {
+ map->resetZoom();
+}
+
+void NativeMapView::setMinZoom(jni::JNIEnv&, jni::jdouble zoom) {
+ map->setMinZoom(zoom);
+}
+
+jni::jdouble NativeMapView::getMinZoom(jni::JNIEnv&) {
+ return map->getMinZoom();
+}
+
+void NativeMapView::setMaxZoom(jni::JNIEnv&, jni::jdouble zoom) {
+ map->setMaxZoom(zoom);
+}
+
+jni::jdouble NativeMapView::getMaxZoom(jni::JNIEnv&) {
+ return map->getMaxZoom();
+}
+
+void NativeMapView::rotateBy(jni::JNIEnv&, jni::jdouble sx, jni::jdouble sy, jni::jdouble ex, jni::jdouble ey) {
+ mbgl::ScreenCoordinate first(sx, sy);
+ mbgl::ScreenCoordinate second(ex, ey);
+ map->rotateBy(first, second);
+}
+
+void NativeMapView::setBearing(jni::JNIEnv&, jni::jdouble degrees) {
+ map->setBearing(degrees);
+}
+
+void NativeMapView::setBearingXY(jni::JNIEnv&, jni::jdouble degrees, jni::jdouble cx, jni::jdouble cy) {
+ mbgl::ScreenCoordinate center(cx, cy);
+ map->setBearing(degrees, center);
+}
+
+jni::jdouble NativeMapView::getBearing(jni::JNIEnv&) {
+ return map->getBearing();
+}
+
+void NativeMapView::resetNorth(jni::JNIEnv&) {
+ map->resetNorth();
+}
+
+void NativeMapView::setVisibleCoordinateBounds(JNIEnv& env, jni::Array<jni::Object<LatLng>> coordinates, jni::Object<RectF> padding, jdouble direction) {
+ NullCheck(env, &coordinates);
+ std::size_t count = coordinates.Length(env);
+
+ std::vector<mbgl::LatLng> latLngs;
+ latLngs.reserve(count);
+
+ for (std::size_t i = 0; i < count; i++) {
+ auto latLng = coordinates.Get(env, i);
+ latLngs.push_back(LatLng::getLatLng(env, latLng));
+ jni::DeleteLocalRef(env, latLng);
+ }
+
+ mbgl::EdgeInsets mbglInsets = { RectF::getTop(env, padding), RectF::getLeft(env, padding), RectF::getBottom(env, padding), RectF::getRight(env, padding) };
+ mbgl::CameraOptions cameraOptions = map->cameraForLatLngs(latLngs, mbglInsets);
+ if (direction >= 0) {
+ // convert from degrees to radians
+ cameraOptions.angle = (-direction * M_PI) / 180;
+ }
+
+ mbgl::AnimationOptions animationOptions;
+ map->easeTo(cameraOptions, animationOptions);
+}
+
+void NativeMapView::setContentPadding(JNIEnv&, double top, double left, double bottom, double right) {
+ insets = {top, left, bottom, right};
+}
+
+void NativeMapView::scheduleSnapshot(jni::JNIEnv&) {
+ snapshot = true;
+}
+
+void NativeMapView::enableFps(jni::JNIEnv&, jni::jboolean enable) {
fpsEnabled = enable;
}
-void NativeMapView::updateFps() {
- if (!fpsEnabled) {
+jni::Array<jni::jdouble> NativeMapView::getCameraValues(jni::JNIEnv& env) {
+ //Create buffer with values
+ jdouble buf[5];
+ mbgl::LatLng latLng = map->getLatLng(insets);
+ buf[0] = latLng.latitude;
+ buf[1] = latLng.longitude;
+ buf[2] = -map->getBearing();
+ buf[3] = map->getPitch();
+ buf[4] = map->getZoom();
+
+ //Convert to Java array
+ auto output = jni::Array<jni::jdouble>::New(env, 5);
+ jni::SetArrayRegion(env, *output, 0, 5, buf);
+
+ return output;
+}
+
+void NativeMapView::updateMarker(jni::JNIEnv& env, jni::jlong markerId, jni::jdouble lat, jni::jdouble lon, jni::String jid) {
+ if (markerId == -1) {
return;
}
- static int frames = 0;
- static int64_t timeElapsed = 0LL;
+ std::string iconId = jni::Make<std::string>(env, jid);
+ // Because Java only has int, not unsigned int, we need to bump the annotation id up to a long.
+ map->updateAnnotation(markerId, mbgl::SymbolAnnotation { mbgl::Point<double>(lon, lat), iconId });
+}
- frames++;
- struct timespec now;
- clock_gettime(CLOCK_MONOTONIC, &now);
- int64_t currentTime = now.tv_sec * 1000000000LL + now.tv_nsec;
+jni::Array<jni::jlong> NativeMapView::addMarkers(jni::JNIEnv& env, jni::Array<jni::Object<Marker>> jmarkers) {
+ jni::NullCheck(env, &jmarkers);
+ std::size_t len = jmarkers.Length(env);
- if (currentTime - timeElapsed >= 1) {
- fps = frames / ((currentTime - timeElapsed) / 1E9);
- mbgl::Log::Info(mbgl::Event::Render, "FPS: %4.2f", fps);
- timeElapsed = currentTime;
- frames = 0;
+ std::vector<jni::jlong> ids;
+ ids.reserve(len);
+
+ for (std::size_t i = 0; i < len; i++) {
+ jni::Object<Marker> marker = jmarkers.Get(env, i);
+ ids.push_back(map->addAnnotation(mbgl::SymbolAnnotation {
+ Marker::getPosition(env, marker),
+ Marker::getIconId(env, marker)
+ }));
+
+ jni::DeleteLocalRef(env, marker);
}
- assert(vm != nullptr);
- assert(obj != nullptr);
-
- JNIEnv *env2;
- jboolean renderDetach = attach_jni_thread(theJVM, &env2, "Callback Thread");
- if (!renderDetach) {
- env2->CallVoidMethod(obj, onFpsChangedId, fps);
- if(env2->ExceptionCheck()) {
- env2->ExceptionDescribe();
+ auto result = jni::Array<jni::jlong>::New(env, len);
+ result.SetRegion<std::vector<jni::jlong>>(env, 0, ids);
+
+ return result;
+}
+
+void NativeMapView::onLowMemory(JNIEnv&) {
+ map->onLowMemory();
+}
+
+void NativeMapView::setDebug(JNIEnv&, jni::jboolean debug) {
+ DebugOptions debugOptions = debug ? DebugOptions::TileBorders | DebugOptions::ParseStatus | DebugOptions::Collision
+ : DebugOptions::NoDebug;
+ map->setDebug(debugOptions);
+ fpsEnabled = debug;
+}
+
+void NativeMapView::cycleDebugOptions(JNIEnv&) {
+ map->cycleDebugOptions();
+ fpsEnabled = map->getDebug() != DebugOptions::NoDebug;
+}
+
+jni::jboolean NativeMapView::getDebug(JNIEnv&) {
+ return map->getDebug() != DebugOptions::NoDebug;
+}
+
+jni::jboolean NativeMapView::isFullyLoaded(JNIEnv&) {
+ return map->isFullyLoaded();
+}
+
+jni::jdouble NativeMapView::getMetersPerPixelAtLatitude(JNIEnv&, jni::jdouble lat, jni::jdouble zoom) {
+ return map->getMetersPerPixelAtLatitude(lat, zoom);
+}
+
+jni::Object<ProjectedMeters> NativeMapView::projectedMetersForLatLng(JNIEnv& env, jni::jdouble latitude, jni::jdouble longitude) {
+ mbgl::ProjectedMeters projectedMeters = map->projectedMetersForLatLng(mbgl::LatLng(latitude, longitude));
+ return ProjectedMeters::New(env, projectedMeters.northing, projectedMeters.easting);
+}
+
+jni::Object<PointF> NativeMapView::pixelForLatLng(JNIEnv& env, jdouble latitude, jdouble longitude) {
+ mbgl::ScreenCoordinate pixel = map->pixelForLatLng(mbgl::LatLng(latitude, longitude));
+ return PointF::New(env, static_cast<float>(pixel.x), static_cast<float>(pixel.y));
+}
+
+jni::Object<LatLng> NativeMapView::latLngForProjectedMeters(JNIEnv& env, jdouble northing, jdouble easting) {
+ mbgl::LatLng latLng = map->latLngForProjectedMeters(mbgl::ProjectedMeters(northing, easting));
+ return LatLng::New(env, latLng.latitude, latLng.longitude);
+}
+
+jni::Object<LatLng> NativeMapView::latLngForPixel(JNIEnv& env, jfloat x, jfloat y) {
+ mbgl::LatLng latLng = map->latLngForPixel(mbgl::ScreenCoordinate(x, y));
+ return LatLng::New(env, latLng.latitude, latLng.longitude);
+}
+
+jni::Array<jlong> NativeMapView::addPolylines(JNIEnv& env, jni::Array<jni::Object<Polyline>> polylines) {
+ NullCheck(env, &polylines);
+ std::size_t len = polylines.Length(env);
+
+ std::vector<jni::jlong> ids;
+ ids.reserve(len);
+
+ for (std::size_t i = 0; i < len; i++) {
+ auto polyline = polylines.Get(env, i);
+
+ mbgl::LineAnnotation annotation = Polyline::toAnnotation(env, polyline);
+ ids.push_back(map->addAnnotation(annotation));
+
+ jni::DeleteLocalRef(env, polyline);
+ }
+
+ auto result = jni::Array<jni::jlong>::New(env, len);
+ result.SetRegion<std::vector<jni::jlong>>(env, 0, ids);
+
+ return result;
+}
+
+
+jni::Array<jlong> NativeMapView::addPolygons(JNIEnv& env, jni::Array<jni::Object<Polygon>> polygons) {
+ NullCheck(env, &polygons);
+ std::size_t len = polygons.Length(env);
+
+ std::vector<jni::jlong> ids;
+ ids.reserve(len);
+
+ for (std::size_t i = 0; i < len; i++) {
+ auto polygon = polygons.Get(env, i);
+
+ mbgl::FillAnnotation annotation = Polygon::toAnnotation(env, polygon);
+ ids.push_back(map->addAnnotation(annotation));
+
+ jni::DeleteLocalRef(env, polygon);
+ }
+
+ auto result = jni::Array<jni::jlong>::New(env, len);
+ result.SetRegion<std::vector<jni::jlong>>(env, 0, ids);
+
+ return result;
+}
+
+//TODO: Move to Polyline class and make native peer
+void NativeMapView::updatePolyline(JNIEnv& env, jlong polylineId, jni::Object<Polyline> polyline) {
+ mbgl::LineAnnotation annotation = Polyline::toAnnotation(env, polyline);
+ map->updateAnnotation(polylineId, annotation);
+}
+
+//TODO: Move to Polygon class and make native peer
+void NativeMapView::updatePolygon(JNIEnv& env, jlong polygonId, jni::Object<Polygon> polygon) {
+ mbgl::FillAnnotation annotation = Polygon::toAnnotation(env, polygon);
+ map->updateAnnotation(polygonId, annotation);
+}
+
+void NativeMapView::removeAnnotations(JNIEnv& env, jni::Array<jlong> ids) {
+ NullCheck(env, &ids);
+ std::size_t len = ids.Length(env);
+ auto elements = jni::GetArrayElements(env, *ids);
+ jlong* jids = std::get<0>(elements).get();
+
+ for (std::size_t i = 0; i < len; i++) {
+ if(jids[i] == -1L) {
+ continue;
}
+ map->removeAnnotation(jids[i]);
}
}
-void NativeMapView::onViewportChanged(int w, int h) {
- resizeView((int) w / pixelRatio, (int) h / pixelRatio);
- resizeFramebuffer(w, h);
+void NativeMapView::addAnnotationIcon(JNIEnv& env, jni::String symbol, jint w, jint h, jfloat scale, jni::Array<jbyte> jpixels) {
+ const std::string symbolName = jni::Make<std::string>(env, symbol);
+
+ NullCheck(env, &jpixels);
+ std::size_t size = jpixels.Length(env);
+
+ mbgl::PremultipliedImage premultipliedImage({ static_cast<uint32_t>(w), static_cast<uint32_t>(h) });
+ if (premultipliedImage.bytes() != uint32_t(size)) {
+ throw mbgl::util::SpriteImageException("Sprite image pixel count mismatch");
+ }
+
+ jni::GetArrayRegion(env, *jpixels, 0, size, reinterpret_cast<jbyte*>(premultipliedImage.data.get()));
+ auto iconImage = std::make_shared<mbgl::SpriteImage>(std::move(premultipliedImage), float(scale));
+ map->addAnnotationIcon(symbolName, iconImage);
+}
+
+jdouble NativeMapView::getTopOffsetPixelsForAnnotationSymbol(JNIEnv& env, jni::String symbolName) {
+ return map->getTopOffsetPixelsForAnnotationIcon(jni::Make<std::string>(env, symbolName));
+}
+
+jlong NativeMapView::getTransitionDuration(JNIEnv&) {
+ const auto transitionOptions = map->getTransitionOptions();
+ return transitionOptions.duration.value_or(mbgl::Duration::zero()).count();
+}
+
+void NativeMapView::setTransitionDuration(JNIEnv&, jlong duration) {
+ auto transitionOptions = map->getTransitionOptions();
+ transitionOptions.duration = std::chrono::duration_cast<mbgl::Duration>(std::chrono::duration<jlong>(duration));
+ map->setTransitionOptions(transitionOptions);
+}
+
+jlong NativeMapView::getTransitionDelay(JNIEnv&) {
+ const auto transitionOptions = map->getTransitionOptions();
+ return transitionOptions.delay.value_or(mbgl::Duration::zero()).count();
+}
+
+void NativeMapView::setTransitionDelay(JNIEnv&, jlong delay) {
+ auto transitionOptions = map->getTransitionOptions();
+ transitionOptions.delay = std::chrono::duration_cast<mbgl::Duration>(std::chrono::duration<jlong>(delay));
+ map->setTransitionOptions(transitionOptions);
+}
+
+jni::Array<jlong> NativeMapView::queryPointAnnotations(JNIEnv& env, jni::Object<RectF> rect) {
+ // Convert input
+ mbgl::ScreenBox box = {
+ { RectF::getLeft(env, rect), RectF::getTop(env, rect) },
+ { RectF::getRight(env, rect), RectF::getBottom(env, rect) },
+ };
+
+ // Assume only points for now
+ mbgl::AnnotationIDs ids = map->queryPointAnnotations(box);
+
+ // Convert result
+ std::vector<jlong> longIds(ids.begin(), ids.end());
+ auto result = jni::Array<jni::jlong>::New(env, ids.size());
+ result.SetRegion<std::vector<jni::jlong>>(env, 0, longIds);
+
+ return result;
+}
+
+jni::Array<jni::Object<Feature>> NativeMapView::queryRenderedFeaturesForPoint(JNIEnv& env, jni::jfloat x, jni::jfloat y, jni::Array<jni::String> layerIds) {
+ using namespace mbgl::android::conversion;
+ using namespace mapbox::geometry;
+
+ mbgl::optional<std::vector<std::string>> layers;
+ if (layerIds != nullptr && layerIds.Length(env) > 0) {
+ layers = toVector(env, layerIds);
+ }
+ point<double> point = {x, y};
+
+ return *convert<jni::Array<jni::Object<Feature>>, std::vector<mbgl::Feature>>(env, map->queryRenderedFeatures(point, layers));
+}
+
+jni::Array<jni::Object<Feature>> NativeMapView::queryRenderedFeaturesForBox(JNIEnv& env, jni::jfloat left, jni::jfloat top, jni::jfloat right, jni::jfloat bottom, jni::Array<jni::String> layerIds) {
+ using namespace mbgl::android::conversion;
+ using namespace mapbox::geometry;
+
+ mbgl::optional<std::vector<std::string>> layers;
+ if (layerIds != nullptr && layerIds.Length(env) > 0) {
+ layers = toVector(env, layerIds);
+ }
+ box<double> box = { point<double>{ left, top}, point<double>{ right, bottom } };
+
+ return *convert<jni::Array<jni::Object<Feature>>, std::vector<mbgl::Feature>>(env, map->queryRenderedFeatures(box, layers));
+}
+
+jni::Object<Layer> NativeMapView::getLayer(JNIEnv& env, jni::String layerId) {
+
+ // Find the layer
+ mbgl::style::Layer* coreLayer = map->getLayer(jni::Make<std::string>(env, layerId));
+ if (!coreLayer) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "No layer found");
+ return jni::Object<Layer>();
+ }
+
+ // Create and return the layer's native peer
+ return jni::Object<Layer>(createJavaLayerPeer(env, *map, *coreLayer));
+}
+
+void NativeMapView::addLayer(JNIEnv& env, jlong nativeLayerPtr, jni::String before) {
+ assert(nativeLayerPtr != 0);
+
+ Layer *layer = reinterpret_cast<Layer *>(nativeLayerPtr);
+ try {
+ layer->addToMap(*map, before ? mbgl::optional<std::string>(jni::Make<std::string>(env, before)) : mbgl::optional<std::string>());
+ } catch (const std::runtime_error& error) {
+ jni::ThrowNew(env, jni::FindClass(env, "com/mapbox/mapboxsdk/style/layers/CannotAddLayerException"), error.what());
+ }
+}
+
+/**
+ * Remove by layer id. Ownership is not transferred back
+ */
+void NativeMapView::removeLayerById(JNIEnv& env, jni::String id) {
+ try {
+ map->removeLayer(jni::Make<std::string>(env, id));
+ } catch (const std::runtime_error& error) {
+ jni::ThrowNew(env, jni::FindClass(env, "com/mapbox/mapboxsdk/style/layers/NoSuchLayerException"), error.what());
+ }
+}
+
+/**
+ * Remove with wrapper object id. Ownership is transferred back to the wrapper
+ */
+void NativeMapView::removeLayer(JNIEnv& env, jlong layerPtr) {
+ assert(layerPtr != 0);
+
+ mbgl::android::Layer *layer = reinterpret_cast<mbgl::android::Layer *>(layerPtr);
+ try {
+ std::unique_ptr<mbgl::style::Layer> coreLayer = map->removeLayer(layer->get().getID());
+ layer->setLayer(std::move(coreLayer));
+ } catch (const std::runtime_error& error) {
+ jni::ThrowNew(env, jni::FindClass(env, "com/mapbox/mapboxsdk/style/layers/NoSuchLayerException"), error.what());
+ }
+}
+
+
+jni::Object<Source> NativeMapView::getSource(JNIEnv& env, jni::String sourceId) {
+ // Find the source
+ mbgl::style::Source* coreSource = map->getSource(jni::Make<std::string>(env, sourceId));
+ if (!coreSource) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "No source found");
+ return jni::Object<Source>();
+ }
+
+ // Create and return the source's native peer
+ return jni::Object<Source>(createJavaSourcePeer(env, *map, *coreSource));
+}
+
+void NativeMapView::addSource(JNIEnv& env, jni::jlong sourcePtr) {
+ assert(sourcePtr != 0);
+
+ Source *source = reinterpret_cast<Source *>(sourcePtr);
+ try {
+ source->addToMap(*map);
+ } catch (const std::runtime_error& error) {
+ jni::ThrowNew(env, jni::FindClass(env, "com/mapbox/mapboxsdk/style/sources/CannotAddSourceException"), error.what());
+ }
+}
+
+void NativeMapView::removeSourceById(JNIEnv& env, jni::String id) {
+ try {
+ map->removeSource(jni::Make<std::string>(env, id));
+ } catch (const std::runtime_error& error) {
+ jni::ThrowNew(env, jni::FindClass(env, "com/mapbox/mapboxsdk/style/sources/NoSuchSourceException"), error.what());
+ }
+}
+
+void NativeMapView::removeSource(JNIEnv& env, jlong sourcePtr) {
+ assert(sourcePtr != 0);
+
+ mbgl::android::Source *source = reinterpret_cast<mbgl::android::Source *>(sourcePtr);
+ try {
+ std::unique_ptr<mbgl::style::Source> coreSource = map->removeSource(source->get().getID());
+ source->setSource(std::move(coreSource));
+ } catch (const std::runtime_error& error) {
+ jni::ThrowNew(env, jni::FindClass(env, "com/mapbox/mapboxsdk/style/sources/NoSuchSourceException"), error.what());
+ }
+}
+
+void NativeMapView::addImage(JNIEnv& env, jni::String name, jni::jint w, jni::jint h, jni::jfloat scale, jni::Array<jbyte> pixels) {
+ jni::NullCheck(env, &pixels);
+ std::size_t size = pixels.Length(env);
+
+ mbgl::PremultipliedImage premultipliedImage({ static_cast<uint32_t>(w), static_cast<uint32_t>(h) });
+ if (premultipliedImage.bytes() != uint32_t(size)) {
+ throw mbgl::util::SpriteImageException("Sprite image pixel count mismatch");
+ }
+
+ jni::GetArrayRegion(env, *pixels, 0, size, reinterpret_cast<jbyte*>(premultipliedImage.data.get()));
+ auto spriteImage = std::make_unique<mbgl::SpriteImage>(std::move(premultipliedImage), float(scale));
+
+ map->addImage(jni::Make<std::string>(env, name), std::move(spriteImage));
+}
+
+void NativeMapView::removeImage(JNIEnv& env, jni::String name) {
+ map->removeImage(jni::Make<std::string>(env, name));
+}
+
+// Private methods //
+
+mbgl::Size NativeMapView::getFramebufferSize() const {
+ mbgl::Log::Info(mbgl::Event::Android, "FB size %dx%d", fbWidth, fbHeight);
+ return { static_cast<uint32_t>(fbWidth), static_cast<uint32_t>(fbHeight) };
+}
+
+/**
+ * Called whenever the associated thread needs to wake up (since there is no active run loop)
+ *
+ * May be called from any thread
+ */
+void NativeMapView::wake() {
+ mbgl::Log::Info(mbgl::Event::JNI, "Wake callback");
+ android::UniqueEnv _env = android::AttachEnv();
+ static auto wakeCallback = javaClass.GetMethod<void ()>(*_env, "onWake");
+ javaPeer->Call(*_env, wakeCallback);
+}
+
+void NativeMapView::updateViewBinding() {
+ getContext().bindFramebuffer.setCurrentValue(0);
+ assert(mbgl::gl::value::BindFramebuffer::Get() == getContext().bindFramebuffer.getCurrentValue());
+ getContext().viewport.setCurrentValue({ 0, 0, getFramebufferSize() });
+ assert(mbgl::gl::value::Viewport::Get() == getContext().viewport.getCurrentValue());
}
void NativeMapView::resizeView(int w, int h) {
@@ -244,8 +752,123 @@ void NativeMapView::resizeFramebuffer(int w, int h) {
invalidate();
}
-void NativeMapView::setInsets(mbgl::EdgeInsets insets_) {
- insets = insets_;
+void NativeMapView::updateFps() {
+ if (!fpsEnabled) {
+ return;
+ }
+
+ static int frames = 0;
+ static int64_t timeElapsed = 0LL;
+
+ frames++;
+ struct timespec now;
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ int64_t currentTime = now.tv_sec * 1000000000LL + now.tv_nsec;
+
+ if (currentTime - timeElapsed >= 1) {
+ fps = frames / ((currentTime - timeElapsed) / 1E9);
+ mbgl::Log::Info(mbgl::Event::Render, "FPS: %4.2f", fps);
+ timeElapsed = currentTime;
+ frames = 0;
+ }
+
+ assert(vm != nullptr);
+
+ android::UniqueEnv _env = android::AttachEnv();
+ static auto onFpsChanged = javaClass.GetMethod<void (double)>(*_env, "onFpsChanged");
+ javaPeer->Call(*_env, onFpsChanged, fps);
+}
+
+// Static methods //
+
+jni::Class<NativeMapView> NativeMapView::javaClass;
+
+void NativeMapView::registerNative(jni::JNIEnv& env) {
+ // Lookup the class
+ NativeMapView::javaClass = *jni::Class<NativeMapView>::Find(env).NewGlobalRef(env).release();
+
+ #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
+
+ // Register the peer
+ jni::RegisterNativePeer<NativeMapView>(env, NativeMapView::javaClass, "nativePtr",
+ std::make_unique<NativeMapView, JNIEnv&, jni::Object<NativeMapView>, jni::String, jni::String, jni::jfloat, jni::jint, jni::jlong>,
+ "initialize",
+ "destroy",
+ METHOD(&NativeMapView::render, "render"),
+ METHOD(&NativeMapView::onViewportChanged, "_onViewportChanged"),
+ METHOD(&NativeMapView::setAPIBaseUrl , "setApiBaseUrl"),
+ METHOD(&NativeMapView::getStyleUrl, "getStyleUrl"),
+ METHOD(&NativeMapView::setStyleUrl, "setStyleUrl"),
+ METHOD(&NativeMapView::getStyleJson, "getStyleJson"),
+ METHOD(&NativeMapView::setStyleJson, "setStyleJson"),
+ METHOD(&NativeMapView::getAccessToken, "getAccessToken"),
+ METHOD(&NativeMapView::setAccessToken, "setAccessToken"),
+ METHOD(&NativeMapView::cancelTransitions, "cancelTransitions"),
+ METHOD(&NativeMapView::setGestureInProgress, "setGestureInProgress"),
+ METHOD(&NativeMapView::moveBy, "_moveBy"),
+ METHOD(&NativeMapView::getLatLng, "_getLatLng"),
+ METHOD(&NativeMapView::setLatLng, "setLatLng"),
+ METHOD(&NativeMapView::setReachability, "setReachability"),
+ METHOD(&NativeMapView::resetPosition, "resetPosition"),
+ METHOD(&NativeMapView::getPitch, "getPitch"),
+ METHOD(&NativeMapView::setPitch, "setPitch"),
+ METHOD(&NativeMapView::scaleBy, "_scaleBy"),
+ METHOD(&NativeMapView::setScale, "_setScale"),
+ METHOD(&NativeMapView::getScale, "getScale"),
+ METHOD(&NativeMapView::setZoom, "setZoom"),
+ METHOD(&NativeMapView::getZoom, "getZoom"),
+ METHOD(&NativeMapView::resetZoom, "resetZoom"),
+ METHOD(&NativeMapView::setMinZoom, "setMinZoom"),
+ METHOD(&NativeMapView::getMinZoom, "getMinZoom"),
+ METHOD(&NativeMapView::setMaxZoom, "setMaxZoom"),
+ METHOD(&NativeMapView::getMaxZoom, "getMaxZoom"),
+ METHOD(&NativeMapView::rotateBy, "_rotateBy"),
+ METHOD(&NativeMapView::setBearing, "setBearing"),
+ METHOD(&NativeMapView::setBearingXY, "_setBearingXY"),
+ METHOD(&NativeMapView::getBearing, "getBearing"),
+ METHOD(&NativeMapView::resetNorth, "resetNorth"),
+ METHOD(&NativeMapView::setVisibleCoordinateBounds, "setVisibleCoordinateBounds"),
+ METHOD(&NativeMapView::setContentPadding, "setContentPadding"),
+ METHOD(&NativeMapView::scheduleSnapshot, "scheduleSnapshot"),
+ METHOD(&NativeMapView::enableFps, "enableFps"),
+ METHOD(&NativeMapView::getCameraValues, "getCameraValues"),
+ METHOD(&NativeMapView::updateMarker, "updateMarker"),
+ METHOD(&NativeMapView::addMarkers, "addMarkers"),
+ METHOD(&NativeMapView::setDebug, "setDebug"),
+ METHOD(&NativeMapView::cycleDebugOptions, "cycleDebugOptions"),
+ METHOD(&NativeMapView::getDebug, "getDebug"),
+ METHOD(&NativeMapView::isFullyLoaded, "isFullyLoaded"),
+ METHOD(&NativeMapView::onLowMemory, "onLowMemory"),
+ METHOD(&NativeMapView::getMetersPerPixelAtLatitude, "getMetersPerPixelAtLatitude"),
+ METHOD(&NativeMapView::projectedMetersForLatLng, "projectedMetersForLatLng"),
+ METHOD(&NativeMapView::pixelForLatLng, "pixelForLatLng"),
+ METHOD(&NativeMapView::latLngForProjectedMeters, "latLngForProjectedMeters"),
+ METHOD(&NativeMapView::latLngForPixel, "latLngForPixel"),
+ METHOD(&NativeMapView::addPolylines, "addPolylines"),
+ METHOD(&NativeMapView::addPolygons, "addPolygons"),
+ METHOD(&NativeMapView::updatePolyline, "updatePolyline"),
+ METHOD(&NativeMapView::updatePolygon, "updatePolygon"),
+ METHOD(&NativeMapView::removeAnnotations, "removeAnnotations"),
+ METHOD(&NativeMapView::addAnnotationIcon, "addAnnotationIcon"),
+ METHOD(&NativeMapView::getTopOffsetPixelsForAnnotationSymbol, "getTopOffsetPixelsForAnnotationSymbol"),
+ METHOD(&NativeMapView::getTransitionDuration, "getTransitionDuration"),
+ METHOD(&NativeMapView::setTransitionDuration, "setTransitionDuration"),
+ METHOD(&NativeMapView::getTransitionDelay, "getTransitionDelay"),
+ METHOD(&NativeMapView::setTransitionDelay, "setTransitionDelay"),
+ METHOD(&NativeMapView::queryPointAnnotations, "queryPointAnnotations"),
+ METHOD(&NativeMapView::queryRenderedFeaturesForPoint, "queryRenderedFeaturesForPoint"),
+ METHOD(&NativeMapView::queryRenderedFeaturesForBox, "queryRenderedFeaturesForBox"),
+ METHOD(&NativeMapView::getLayer, "getLayer"),
+ METHOD(&NativeMapView::addLayer, "addLayer"),
+ METHOD(&NativeMapView::removeLayerById, "removeLayerById"),
+ METHOD(&NativeMapView::removeLayer, "removeLayer"),
+ METHOD(&NativeMapView::getSource, "getSource"),
+ METHOD(&NativeMapView::addSource, "addSource"),
+ METHOD(&NativeMapView::removeSourceById, "removeSourceById"),
+ METHOD(&NativeMapView::removeSource, "removeSource"),
+ METHOD(&NativeMapView::addImage, "addImage"),
+ METHOD(&NativeMapView::removeImage, "removeImage")
+ );
}
}
diff --git a/platform/android/src/native_map_view.hpp b/platform/android/src/native_map_view.hpp
index 81274f3a24..185bb7b65c 100755
--- a/platform/android/src/native_map_view.hpp
+++ b/platform/android/src/native_map_view.hpp
@@ -1,22 +1,44 @@
#pragma once
+#include <mbgl/map/backend.hpp>
+#include <mbgl/map/camera.hpp>
#include <mbgl/map/map.hpp>
#include <mbgl/map/view.hpp>
-#include <mbgl/map/backend.hpp>
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/util/default_thread_pool.hpp>
#include <mbgl/util/run_loop.hpp>
#include <mbgl/storage/default_file_source.hpp>
+#include <mbgl/storage/network_status.hpp>
+
+#include "annotation/marker.hpp"
+#include "annotation/polygon.hpp"
+#include "annotation/polyline.hpp"
+#include "graphics/pointF.hpp"
+#include "graphics/rectF.hpp"
+#include "geometry/feature.hpp"
+#include "geometry/lat_lng.hpp"
+#include "geometry/projected_meters.hpp"
+#include "style/layers/layers.hpp"
+#include "style/sources/sources.hpp"
#include <string>
#include <jni.h>
+#include <jni/jni.hpp>
namespace mbgl {
namespace android {
-class NativeMapView : public mbgl::View, public mbgl::Backend {
+class NativeMapView : public View, public Backend {
public:
- NativeMapView(JNIEnv *env, jobject obj, float pixelRatio, int availableProcessors, size_t totalMemory);
+
+ static constexpr auto Name() { return "com/mapbox/mapboxsdk/maps/NativeMapView"; };
+
+ static jni::Class<NativeMapView> javaClass;
+
+ static void registerNative(jni::JNIEnv&);
+
+ NativeMapView(jni::JNIEnv&, jni::Object<NativeMapView>, jni::String, jni::String, jni::jfloat, jni::jint, jni::jlong);
+
virtual ~NativeMapView();
// mbgl::View //
@@ -30,22 +52,158 @@ public:
// JNI //
- mbgl::Map &getMap();
- mbgl::DefaultFileSource &getFileSource();
+ void destroy(jni::JNIEnv&);
+
+ void render(jni::JNIEnv&);
+
+ void onViewportChanged(jni::JNIEnv&, jni::jint width, jni::jint height);
+
+ void setAPIBaseUrl(jni::JNIEnv&, jni::String);
+
+ jni::String getStyleUrl(jni::JNIEnv&);
+
+ void setStyleUrl(jni::JNIEnv&, jni::String);
+
+ jni::String getStyleJson(jni::JNIEnv&);
+
+ void setStyleJson(jni::JNIEnv&, jni::String);
+
+ jni::String getAccessToken(jni::JNIEnv&);
+
+ void setAccessToken(jni::JNIEnv&, jni::String);
+
+ void cancelTransitions(jni::JNIEnv&);
+
+ void setGestureInProgress(jni::JNIEnv&, jni::jboolean);
+
+ void moveBy(jni::JNIEnv&, jni::jdouble, jni::jdouble);
+
+ jni::Object<LatLng> getLatLng(JNIEnv&);
+
+ void setLatLng(jni::JNIEnv&, jni::jdouble, jni::jdouble);
+
+ void setReachability(jni::JNIEnv&, jni::jboolean);
+
+ void resetPosition(jni::JNIEnv&);
+
+ jni::jdouble getPitch(jni::JNIEnv&);
+
+ void setPitch(jni::JNIEnv&, jni::jdouble);
+
+ void scaleBy(jni::JNIEnv&, jni::jdouble, jni::jdouble, jni::jdouble);
+
+ void setScale(jni::JNIEnv&, jni::jdouble, jni::jdouble, jni::jdouble);
+
+ jni::jdouble getScale(jni::JNIEnv&);
+
+ void setZoom(jni::JNIEnv&, jni::jdouble);
+
+ jni::jdouble getZoom(jni::JNIEnv&);
+
+ void resetZoom(jni::JNIEnv&);
+
+ void setMinZoom(jni::JNIEnv&, jni::jdouble);
+
+ jni::jdouble getMinZoom(jni::JNIEnv&);
+
+ void setMaxZoom(jni::JNIEnv&, jni::jdouble);
+
+ jni::jdouble getMaxZoom(jni::JNIEnv&);
+
+ void rotateBy(jni::JNIEnv&, jni::jdouble, jni::jdouble, jni::jdouble, jni::jdouble);
+
+ void setBearing(jni::JNIEnv&, jni::jdouble);
+
+ void setBearingXY(jni::JNIEnv&, jni::jdouble, jni::jdouble, jni::jdouble);
+
+ jni::jdouble getBearing(jni::JNIEnv&);
+
+ void resetNorth(jni::JNIEnv&);
+
+ void setVisibleCoordinateBounds(JNIEnv&, jni::Array<jni::Object<LatLng>>, jni::Object<RectF>, jdouble);
+
+ void setContentPadding(JNIEnv&, double, double, double, double);
+
+ void scheduleSnapshot(jni::JNIEnv&);
+
+ void enableFps(jni::JNIEnv&, jni::jboolean enable);
+
+ jni::Array<jni::jdouble> getCameraValues(jni::JNIEnv&);
+
+ void updateMarker(jni::JNIEnv&, jni::jlong, jni::jdouble, jni::jdouble, jni::String);
+
+ jni::Array<jni::jlong> addMarkers(jni::JNIEnv&, jni::Array<jni::Object<Marker>>);
+
+ void onLowMemory(JNIEnv& env);
+
+ void setDebug(JNIEnv&, jni::jboolean);
+
+ void cycleDebugOptions(JNIEnv&);
+
+ jni::jboolean getDebug(JNIEnv&);
+
+ jni::jboolean isFullyLoaded(JNIEnv&);
+
+ jni::jdouble getMetersPerPixelAtLatitude(JNIEnv&, jni::jdouble, jni::jdouble);
+
+ jni::Object<ProjectedMeters> projectedMetersForLatLng(JNIEnv&, jni::jdouble, jni::jdouble);
+
+ jni::Object<PointF> pixelForLatLng(JNIEnv&, jdouble, jdouble);
+
+ jni::Object<LatLng> latLngForProjectedMeters(JNIEnv&, jdouble, jdouble);
+
+ jni::Object<LatLng> latLngForPixel(JNIEnv&, jfloat, jfloat);
+
+ jni::Array<jlong> addPolylines(JNIEnv&, jni::Array<jni::Object<Polyline>>);
+
+ jni::Array<jlong> addPolygons(JNIEnv&, jni::Array<jni::Object<Polygon>>);
+
+ void updatePolyline(JNIEnv&, jlong, jni::Object<Polyline>);
+
+ void updatePolygon(JNIEnv&, jlong, jni::Object<Polygon>);
+
+ void removeAnnotations(JNIEnv&, jni::Array<jlong>);
+
+ void addAnnotationIcon(JNIEnv&, jni::String, jint, jint, jfloat, jni::Array<jbyte>);
+
+ jdouble getTopOffsetPixelsForAnnotationSymbol(JNIEnv&, jni::String);
+
+ jlong getTransitionDuration(JNIEnv&);
+
+ void setTransitionDuration(JNIEnv&, jlong);
+
+ jlong getTransitionDelay(JNIEnv&);
+
+ void setTransitionDelay(JNIEnv&, jlong);
+
+ jni::Array<jlong> queryPointAnnotations(JNIEnv&, jni::Object<RectF>);
+
+ jni::Array<jni::Object<Feature>> queryRenderedFeaturesForPoint(JNIEnv&, jni::jfloat, jni::jfloat, jni::Array<jni::String>);
+
+ jni::Array<jni::Object<Feature>> queryRenderedFeaturesForBox(JNIEnv&, jni::jfloat, jni::jfloat, jni::jfloat, jni::jfloat, jni::Array<jni::String>);
+
+ jni::Object<Layer> getLayer(JNIEnv&, jni::String);
+
+ void addLayer(JNIEnv&, jlong, jni::String);
+
+ void removeLayerById(JNIEnv&, jni::String);
+
+ void removeLayer(JNIEnv&, jlong);
+
+ jni::Object<Source> getSource(JNIEnv&, jni::String);
- void render();
+ void addSource(JNIEnv&, jni::jlong);
- void enableFps(bool enable);
+ void removeSourceById(JNIEnv&, jni::String);
- void onViewportChanged(int width, int height);
+ void removeSource(JNIEnv&, jlong);
- mbgl::EdgeInsets getInsets() { return insets;}
- void setInsets(mbgl::EdgeInsets insets_);
+ void addImage(JNIEnv&, jni::String, jni::jint, jni::jint, jni::jfloat, jni::Array<jbyte>);
- void scheduleTakeSnapshot();
+ void removeImage(JNIEnv&, jni::String);
protected:
- // Unused //
+ // Unused methods from mbgl::Backend //
void activate() override {};
void deactivate() override {};
@@ -63,8 +221,7 @@ private:
private:
JavaVM *vm = nullptr;
- JNIEnv *env = nullptr;
- jweak obj = nullptr;
+ jni::UniqueWeakObject<NativeMapView> javaPeer;
std::string styleUrl;
std::string apiKey;
@@ -72,6 +229,7 @@ private:
float pixelRatio;
bool fpsEnabled = false;
bool snapshot = false;
+ bool firstRender = true;
double fps = 0.0;
int width = 0;
diff --git a/platform/android/src/style/android_conversion.hpp b/platform/android/src/style/android_conversion.hpp
index 8ae694d115..d9b88ab52b 100644
--- a/platform/android/src/style/android_conversion.hpp
+++ b/platform/android/src/style/android_conversion.hpp
@@ -4,7 +4,6 @@
#include <mbgl/util/logging.hpp>
#include <mbgl/style/conversion.hpp>
-#include <mbgl/util/feature.hpp>
#include <mbgl/util/optional.hpp>
#include <jni/jni.hpp>