summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortobrun <tobrun.van.nuland@gmail.com>2019-04-04 11:09:28 +0200
committertobrun <tobrun.van.nuland@gmail.com>2019-04-12 13:29:29 +0200
commit8735d3d6086e80fcaccca7f51571de82f16c6cc4 (patch)
treea2faa71581a90b026585393ed312439c23555965
parent8c5c4dd5657852dbd82acdf30927d8af9d2f87f6 (diff)
downloadqtlocation-mapboxgl-upstream/tvn-onstyleimagemissing.tar.gz
[android] - add style image missing binding integration, add synchronousupstream/tvn-onstyleimagemissing
image overloads to style
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapChangeReceiver.java25
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java83
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java14
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Style.java116
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/ImageMissingTest.kt91
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolLayerActivity.java15
-rw-r--r--platform/android/src/android_renderer_frontend.cpp4
-rwxr-xr-xplatform/android/src/native_map_view.cpp12
-rwxr-xr-xplatform/android/src/native_map_view.hpp1
10 files changed, 303 insertions, 60 deletions
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapChangeReceiver.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapChangeReceiver.java
index 7eebd27d62..3a27a9a111 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapChangeReceiver.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapChangeReceiver.java
@@ -31,6 +31,8 @@ class MapChangeReceiver implements NativeMapView.StateCallback {
private final List<MapView.OnDidFinishLoadingStyleListener> onDidFinishLoadingStyleListenerList
= new CopyOnWriteArrayList<>();
private final List<MapView.OnSourceChangedListener> onSourceChangedListenerList = new CopyOnWriteArrayList<>();
+ private final List<MapView.OnStyleImageMissingListener> onStyleImageMissingListenerList
+ = new CopyOnWriteArrayList<>();
@Override
public void onCameraWillChange(boolean animated) {
@@ -214,6 +216,20 @@ class MapChangeReceiver implements NativeMapView.StateCallback {
}
}
+ @Override
+ public void onStyleImageMissing(String imageId) {
+ try {
+ if (!onStyleImageMissingListenerList.isEmpty()) {
+ for (MapView.OnStyleImageMissingListener listener : onStyleImageMissingListenerList) {
+ listener.onStyleImageMissing(imageId);
+ }
+ }
+ } catch (Throwable err) {
+ Logger.e(TAG, "Exception in onStyleImageMissing", err);
+ throw err;
+ }
+ }
+
void addOnCameraWillChangeListener(MapView.OnCameraWillChangeListener listener) {
onCameraWillChangeListenerList.add(listener);
}
@@ -318,6 +334,14 @@ class MapChangeReceiver implements NativeMapView.StateCallback {
onSourceChangedListenerList.remove(listener);
}
+ void addOnStyleImageMissingListener(MapView.OnStyleImageMissingListener listener) {
+ onStyleImageMissingListenerList.add(listener);
+ }
+
+ void removeOnStyleImageMissingListener(MapView.OnStyleImageMissingListener listener) {
+ onStyleImageMissingListenerList.remove(listener);
+ }
+
void clear() {
onCameraWillChangeListenerList.clear();
onCameraIsChangingListenerList.clear();
@@ -332,5 +356,6 @@ class MapChangeReceiver implements NativeMapView.StateCallback {
onDidBecomeIdleListenerList.clear();
onDidFinishLoadingStyleListenerList.clear();
onSourceChangedListenerList.clear();
+ onStyleImageMissingListenerList.clear();
}
} \ No newline at end of file
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 5a410c247e..0d6e23fe21 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
@@ -553,7 +553,7 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
*
* @param listener The callback that's invoked when the camera region will change
*/
- public void addOnCameraWillChangeListener(OnCameraWillChangeListener listener) {
+ public void addOnCameraWillChangeListener(@NonNull OnCameraWillChangeListener listener) {
mapChangeReceiver.addOnCameraWillChangeListener(listener);
}
@@ -562,7 +562,7 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
*
* @param listener The callback that's invoked when the camera region will change
*/
- public void removeOnCameraWillChangeListener(OnCameraWillChangeListener listener) {
+ public void removeOnCameraWillChangeListener(@NonNull OnCameraWillChangeListener listener) {
mapChangeReceiver.removeOnCameraWillChangeListener(listener);
}
@@ -571,7 +571,7 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
*
* @param listener The callback that's invoked when the camera is changing
*/
- public void addOnCameraIsChangingListener(OnCameraIsChangingListener listener) {
+ public void addOnCameraIsChangingListener(@NonNull OnCameraIsChangingListener listener) {
mapChangeReceiver.addOnCameraIsChangingListener(listener);
}
@@ -580,7 +580,7 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
*
* @param listener The callback that's invoked when the camera is changing
*/
- public void removeOnCameraIsChangingListener(OnCameraIsChangingListener listener) {
+ public void removeOnCameraIsChangingListener(@NonNull OnCameraIsChangingListener listener) {
mapChangeReceiver.removeOnCameraIsChangingListener(listener);
}
@@ -589,7 +589,7 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
*
* @param listener The callback that's invoked when the camera region did change
*/
- public void addOnCameraDidChangeListener(OnCameraDidChangeListener listener) {
+ public void addOnCameraDidChangeListener(@NonNull OnCameraDidChangeListener listener) {
mapChangeReceiver.addOnCameraDidChangeListener(listener);
}
@@ -598,7 +598,7 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
*
* @param listener The callback that's invoked when the camera region did change
*/
- public void removeOnCameraDidChangeListener(OnCameraDidChangeListener listener) {
+ public void removeOnCameraDidChangeListener(@NonNull OnCameraDidChangeListener listener) {
mapChangeReceiver.removeOnCameraDidChangeListener(listener);
}
@@ -607,7 +607,7 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
*
* @param listener The callback that's invoked when the map will start loading
*/
- public void addOnWillStartLoadingMapListener(OnWillStartLoadingMapListener listener) {
+ public void addOnWillStartLoadingMapListener(@NonNull OnWillStartLoadingMapListener listener) {
mapChangeReceiver.addOnWillStartLoadingMapListener(listener);
}
@@ -616,7 +616,7 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
*
* @param listener The callback that's invoked when the map will start loading
*/
- public void removeOnWillStartLoadingMapListener(OnWillStartLoadingMapListener listener) {
+ public void removeOnWillStartLoadingMapListener(@NonNull OnWillStartLoadingMapListener listener) {
mapChangeReceiver.removeOnWillStartLoadingMapListener(listener);
}
@@ -625,7 +625,7 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
*
* @param listener The callback that's invoked when the map has finished loading
*/
- public void addOnDidFinishLoadingMapListener(OnDidFinishLoadingMapListener listener) {
+ public void addOnDidFinishLoadingMapListener(@NonNull OnDidFinishLoadingMapListener listener) {
mapChangeReceiver.addOnDidFinishLoadingMapListener(listener);
}
@@ -634,7 +634,7 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
*
* @param listener The callback that's invoked when the map has finished loading
*/
- public void removeOnDidFinishLoadingMapListener(OnDidFinishLoadingMapListener listener) {
+ public void removeOnDidFinishLoadingMapListener(@NonNull OnDidFinishLoadingMapListener listener) {
mapChangeReceiver.removeOnDidFinishLoadingMapListener(listener);
}
@@ -643,7 +643,7 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
*
* @param listener The callback that's invoked when the map failed to load
*/
- public void addOnDidFailLoadingMapListener(OnDidFailLoadingMapListener listener) {
+ public void addOnDidFailLoadingMapListener(@NonNull OnDidFailLoadingMapListener listener) {
mapChangeReceiver.addOnDidFailLoadingMapListener(listener);
}
@@ -652,7 +652,7 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
*
* @param listener The callback that's invoked when the map failed to load
*/
- public void removeOnDidFailLoadingMapListener(OnDidFailLoadingMapListener listener) {
+ public void removeOnDidFailLoadingMapListener(@NonNull OnDidFailLoadingMapListener listener) {
mapChangeReceiver.removeOnDidFailLoadingMapListener(listener);
}
@@ -661,7 +661,7 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
*
* @param listener The callback that's invoked when the camera will start rendering a frame
*/
- public void addOnWillStartRenderingFrameListener(OnWillStartRenderingFrameListener listener) {
+ public void addOnWillStartRenderingFrameListener(@NonNull OnWillStartRenderingFrameListener listener) {
mapChangeReceiver.addOnWillStartRenderingFrameListener(listener);
}
@@ -670,7 +670,7 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
*
* @param listener The callback that's invoked when the camera will start rendering a frame
*/
- public void removeOnWillStartRenderingFrameListener(OnWillStartRenderingFrameListener listener) {
+ public void removeOnWillStartRenderingFrameListener(@NonNull OnWillStartRenderingFrameListener listener) {
mapChangeReceiver.removeOnWillStartRenderingFrameListener(listener);
}
@@ -679,7 +679,7 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
*
* @param listener The callback that's invoked when the map has finished rendering a frame
*/
- public void addOnDidFinishRenderingFrameListener(OnDidFinishRenderingFrameListener listener) {
+ public void addOnDidFinishRenderingFrameListener(@NonNull OnDidFinishRenderingFrameListener listener) {
mapChangeReceiver.addOnDidFinishRenderingFrameListener(listener);
}
@@ -688,7 +688,7 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
*
* @param listener The callback that's invoked when the map has finished rendering a frame
*/
- public void removeOnDidFinishRenderingFrameListener(OnDidFinishRenderingFrameListener listener) {
+ public void removeOnDidFinishRenderingFrameListener(@NonNull OnDidFinishRenderingFrameListener listener) {
mapChangeReceiver.removeOnDidFinishRenderingFrameListener(listener);
}
@@ -697,7 +697,7 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
*
* @param listener The callback that's invoked when the map will start rendering
*/
- public void addOnWillStartRenderingMapListener(OnWillStartRenderingMapListener listener) {
+ public void addOnWillStartRenderingMapListener(@NonNull OnWillStartRenderingMapListener listener) {
mapChangeReceiver.addOnWillStartRenderingMapListener(listener);
}
@@ -706,7 +706,7 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
*
* @param listener The callback that's invoked when the map will start rendering
*/
- public void removeOnWillStartRenderingMapListener(OnWillStartRenderingMapListener listener) {
+ public void removeOnWillStartRenderingMapListener(@NonNull OnWillStartRenderingMapListener listener) {
mapChangeReceiver.removeOnWillStartRenderingMapListener(listener);
}
@@ -715,7 +715,7 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
*
* @param listener The callback that's invoked when the map has finished rendering
*/
- public void addOnDidFinishRenderingMapListener(OnDidFinishRenderingMapListener listener) {
+ public void addOnDidFinishRenderingMapListener(@NonNull OnDidFinishRenderingMapListener listener) {
mapChangeReceiver.addOnDidFinishRenderingMapListener(listener);
}
@@ -733,7 +733,7 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
*
* @param listener The callback that's invoked when the map has entered the idle state.
*/
- public void addOnDidBecomeIdleListener(OnDidBecomeIdleListener listener) {
+ public void addOnDidBecomeIdleListener(@NonNull OnDidBecomeIdleListener listener) {
mapChangeReceiver.addOnDidBecomeIdleListener(listener);
}
@@ -742,7 +742,7 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
*
* @param listener The callback that's invoked when the map has entered the idle state.
*/
- public void removeOnDidBecomeIdleListener(OnDidBecomeIdleListener listener) {
+ public void removeOnDidBecomeIdleListener(@NonNull OnDidBecomeIdleListener listener) {
mapChangeReceiver.removeOnDidBecomeIdleListener(listener);
}
@@ -753,7 +753,7 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
*
* @param listener The callback that's invoked when the style has finished loading
*/
- public void addOnDidFinishLoadingStyleListener(OnDidFinishLoadingStyleListener listener) {
+ public void addOnDidFinishLoadingStyleListener(@NonNull OnDidFinishLoadingStyleListener listener) {
mapChangeReceiver.addOnDidFinishLoadingStyleListener(listener);
}
@@ -762,7 +762,7 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
*
* @param listener The callback that's invoked when the style has finished loading
*/
- public void removeOnDidFinishLoadingStyleListener(OnDidFinishLoadingStyleListener listener) {
+ public void removeOnDidFinishLoadingStyleListener(@NonNull OnDidFinishLoadingStyleListener listener) {
mapChangeReceiver.removeOnDidFinishLoadingStyleListener(listener);
}
@@ -771,7 +771,7 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
*
* @param listener The callback that's invoked when the source has changed
*/
- public void addOnSourceChangedListener(OnSourceChangedListener listener) {
+ public void addOnSourceChangedListener(@NonNull OnSourceChangedListener listener) {
mapChangeReceiver.addOnSourceChangedListener(listener);
}
@@ -780,11 +780,29 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
*
* @param listener The callback that's invoked when the source has changed
*/
- public void removeOnSourceChangedListener(OnSourceChangedListener listener) {
+ public void removeOnSourceChangedListener(@NonNull OnSourceChangedListener listener) {
mapChangeReceiver.removeOnSourceChangedListener(listener);
}
/**
+ * Set a callback that's invoked when the id of an icon is missing.
+ *
+ * @param listener The callback that's invoked when the id of an icon is missing
+ */
+ public void addOnStyleImageMissingListener(@NonNull OnStyleImageMissingListener listener) {
+ mapChangeReceiver.addOnStyleImageMissingListener(listener);
+ }
+
+ /**
+ * Set a callback that's invoked when a map source has changed.
+ *
+ * @param listener The callback that's invoked when the source has changed
+ */
+ public void removeOnStyleImageMissingListener(@NonNull OnStyleImageMissingListener listener) {
+ mapChangeReceiver.removeOnStyleImageMissingListener(listener);
+ }
+
+ /**
* Interface definition for a callback to be invoked when the camera will change.
* <p>
* {@link MapView#addOnCameraWillChangeListener(OnCameraWillChangeListener)}
@@ -963,6 +981,21 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
}
/**
+ * Interface definition for a callback to be invoked with the id of a missing icon.
+ * <p>
+ * {@link MapView#addOnStyleImageMissingListener(OnStyleImageMissingListener)}
+ * </p>
+ */
+ public interface OnStyleImageMissingListener {
+ /**
+ * Called when the map is missing an icon.
+ *
+ * @param id the id of the icon that is missing
+ */
+ void onStyleImageMissing(@NonNull String id);
+ }
+
+ /**
* Sets a callback object which will be triggered when the {@link MapboxMap} instance is ready to be used.
*
* @param callback The callback object that will be triggered when the map is ready to be used.
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 a5f8be788c..19e550ec90 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
@@ -1022,7 +1022,9 @@ final class NativeMapView implements NativeMap {
@Keep
private void onDidBecomeIdle() {
- stateCallback.onDidBecomeIdle();
+ if (stateCallback != null) {
+ stateCallback.onDidBecomeIdle();
+ }
}
@Keep
@@ -1040,6 +1042,14 @@ final class NativeMapView implements NativeMap {
}
@Keep
+ private void onStyleImageMissing(String imageId) {
+ Logger.e(TAG, "OnStyleImageMissing: " + imageId);
+ if (stateCallback != null) {
+ stateCallback.onStyleImageMissing(imageId);
+ }
+ }
+
+ @Keep
protected void onSnapshotReady(@Nullable Bitmap mapContent) {
if (checkState("OnSnapshotReady")) {
return;
@@ -1455,5 +1465,7 @@ final class NativeMapView implements NativeMap {
void onDidBecomeIdle();
void onSourceChanged(String sourceId);
+
+ void onStyleImageMissing(String imageId);
}
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Style.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Style.java
index 5c28b55de8..84efe6a4af 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Style.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Style.java
@@ -9,7 +9,6 @@ import android.support.annotation.Nullable;
import android.support.annotation.StringDef;
import android.util.DisplayMetrics;
import android.util.Pair;
-
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.style.layers.Layer;
import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
@@ -324,13 +323,49 @@ public class Style {
* @param bitmap the pre-multiplied Bitmap
* @param sdf the flag indicating image is an SDF or template image
*/
- public void addImage(@NonNull final String name, @NonNull final Bitmap bitmap, boolean sdf) {
+ public void addImage(@NonNull final String name, @NonNull Bitmap bitmap, boolean sdf) {
+ validateState("addImage");
+ nativeMap.addImages(new Image[]{toImage(new Builder.ImageWrapper(name, bitmap, sdf))});
+ }
+
+ /**
+ * Adds an image asynchronously, to be used in the map's style.
+ *
+ * @param name the name of the image
+ * @param image the pre-multiplied Bitmap
+ */
+ public void addImageAsync(@NonNull String name, @NonNull Bitmap image) {
+ addImageAsync(name, image, false);
+ }
+
+ /**
+ * Adds an drawable asynchronously, to be converted into a bitmap to be used in the map's style.
+ *
+ * @param name the name of the image
+ * @param drawable the drawable instance to convert
+ */
+ public void addImageAsync(@NonNull String name, @NonNull Drawable drawable) {
+ Bitmap bitmap = BitmapUtils.getBitmapFromDrawable(drawable);
+ if (bitmap == null) {
+ throw new IllegalArgumentException("Provided drawable couldn't be converted to a Bitmap.");
+ }
+ addImageAsync(name, bitmap, false);
+ }
+
+ /**
+ * Adds an image asynchronously, to be used in the map's style.
+ *
+ * @param name the name of the image
+ * @param bitmap the pre-multiplied Bitmap
+ * @param sdf the flag indicating image is an SDF or template image
+ */
+ public void addImageAsync(@NonNull final String name, @NonNull Bitmap bitmap, boolean sdf) {
validateState("addImage");
new BitmapImageConversionTask(nativeMap).execute(new Builder.ImageWrapper(name, bitmap, sdf));
}
/**
- * Adds an images to be used in the map's style.
+ * Adds images to be used in the map's style.
*
* @param images the map of images to add
*/
@@ -339,12 +374,39 @@ public class Style {
}
/**
- * Adds an images to be used in the map's style.
+ * Adds images to be used in the map's style.
*
* @param images the map of images to add
* @param sdf the flag indicating image is an SDF or template image
*/
public void addImages(@NonNull HashMap<String, Bitmap> images, boolean sdf) {
+ validateState("addImage");
+ Image[] convertedImages = new Image[images.size()];
+ int index = 0;
+ for (Builder.ImageWrapper imageWrapper : Builder.ImageWrapper.convertToImageArray(images, sdf)) {
+ convertedImages[index] = toImage(imageWrapper);
+ index++;
+ }
+
+ nativeMap.addImages(convertedImages);
+ }
+
+ /**
+ * Adds images asynchronously, to be used in the map's style.
+ *
+ * @param images the map of images to add
+ */
+ public void addImagesAsync(@NonNull HashMap<String, Bitmap> images) {
+ addImagesAsync(images, false);
+ }
+
+ /**
+ * Adds images asynchronously, to be used in the map's style.
+ *
+ * @param images the map of images to add
+ * @param sdf the flag indicating image is an SDF or template image
+ */
+ public void addImagesAsync(@NonNull HashMap<String, Bitmap> images, boolean sdf) {
validateState("addImages");
new BitmapImageConversionTask(nativeMap).execute(Builder.ImageWrapper.convertToImageArray(images, sdf));
}
@@ -903,7 +965,22 @@ public class Style {
}
}
- private static class BitmapImageConversionTask extends AsyncTask<Builder.ImageWrapper, Void, List<Image>> {
+ private static Image toImage(Builder.ImageWrapper imageWrapper) {
+ Bitmap bitmap = imageWrapper.bitmap;
+ if (bitmap.getConfig() != Bitmap.Config.ARGB_8888) {
+ bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, false);
+ }
+
+ ByteBuffer buffer = ByteBuffer.allocate(bitmap.getByteCount());
+ bitmap.copyPixelsToBuffer(buffer);
+ float pixelRatio = (float) bitmap.getDensity() / DisplayMetrics.DENSITY_DEFAULT;
+
+ return new Image(buffer.array(), pixelRatio, imageWrapper.id,
+ bitmap.getWidth(), bitmap.getHeight(), imageWrapper.sdf
+ );
+ }
+
+ private static class BitmapImageConversionTask extends AsyncTask<Builder.ImageWrapper, Void, Image[]> {
private WeakReference<NativeMap> nativeMap;
@@ -913,39 +990,20 @@ public class Style {
@NonNull
@Override
- protected List<Image> doInBackground(Builder.ImageWrapper... params) {
+ protected Image[] doInBackground(Builder.ImageWrapper... params) {
List<Image> images = new ArrayList<>();
- ByteBuffer buffer;
- String name;
- Bitmap bitmap;
- boolean sdf;
-
for (Builder.ImageWrapper param : params) {
- name = param.id;
- bitmap = param.bitmap;
- sdf = param.sdf;
-
- if (bitmap.getConfig() != Bitmap.Config.ARGB_8888) {
- bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, false);
- }
-
- buffer = ByteBuffer.allocate(bitmap.getByteCount());
- bitmap.copyPixelsToBuffer(buffer);
-
- float pixelRatio = (float) bitmap.getDensity() / DisplayMetrics.DENSITY_DEFAULT;
-
- images.add(new Image(buffer.array(), pixelRatio, name, bitmap.getWidth(), bitmap.getHeight(), sdf));
+ images.add(toImage(param));
}
-
- return images;
+ return images.toArray(new Image[images.size()]);
}
@Override
- protected void onPostExecute(@NonNull List<Image> images) {
+ protected void onPostExecute(@NonNull Image[] images) {
super.onPostExecute(images);
NativeMap nativeMap = this.nativeMap.get();
if (nativeMap != null && !nativeMap.isDestroyed()) {
- nativeMap.addImages(images.toArray(new Image[images.size()]));
+ nativeMap.addImages(images);
}
}
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/ImageMissingTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/ImageMissingTest.kt
new file mode 100644
index 0000000000..c4ea4d2c19
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/ImageMissingTest.kt
@@ -0,0 +1,91 @@
+package com.mapbox.mapboxsdk.testapp.maps
+
+import android.support.test.rule.ActivityTestRule
+import android.support.test.runner.AndroidJUnit4
+import com.mapbox.mapboxsdk.maps.MapView
+import com.mapbox.mapboxsdk.maps.Style
+import com.mapbox.mapboxsdk.testapp.R
+import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity
+import junit.framework.Assert.assertEquals
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
+import java.util.concurrent.TimeoutException
+
+@RunWith(AndroidJUnit4::class)
+class ImageMissingTest {
+
+ @Rule
+ @JvmField
+ var rule = ActivityTestRule(EspressoTestActivity::class.java)
+
+ private lateinit var mapView: MapView
+ private val latch = CountDownLatch(1)
+
+ @Test
+ fun testMissingImage() {
+ rule.runOnUiThread {
+ initMap().addOnStyleImageMissingListener {
+ assertEquals("missing-icon", it)
+ latch.countDown()
+ }
+ }
+
+ if(!latch.await(5, TimeUnit.SECONDS)){
+ throw TimeoutException()
+ }
+ }
+
+ private fun initMap(): MapView {
+ mapView = rule.activity.findViewById(R.id.mapView)
+ mapView.getMapAsync { it.setStyle(Style.Builder().fromJson(styleJson)) }
+ return mapView
+ }
+
+ companion object {
+ private const val styleJson = """
+ {
+ "version": 8,
+ "name": "Mapbox Streets",
+ "sprite": "mapbox://sprites/mapbox/streets-v8",
+ "glyphs": "mapbox://fonts/mapbox/{fontstack}/{range}.pbf",
+ "sources": {
+ "point": {
+ "type": "geojson",
+ "data": {
+ "type": "Feature",
+ "properties": {},
+ "geometry": {
+ "type": "Point",
+ "coordinates": [0, 0]
+ }
+ }
+ }
+ },
+ "layers": [{
+ "id": "bg",
+ "type": "background",
+ "paint": {
+ "background-color": "#f00"
+ }
+ }, {
+ "id": "point",
+ "type": "circle",
+ "source": "point",
+ "paint": {
+ "circle-radius": 100
+ }
+ }, {
+ "id": "icon",
+ "type": "symbol",
+ "source": "point",
+ "layout": {
+ "icon-image": "missing-icon"
+ }
+ }]
+ }
+ """
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java
index 1a2b6c3030..24bfe62e75 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java
@@ -362,7 +362,7 @@ public class SymbolGeneratorActivity extends AppCompatActivity implements OnMapR
@Override
protected void onPostExecute(HashMap<String, Bitmap> bitmapHashMap) {
super.onPostExecute(bitmapHashMap);
- mapboxMap.getStyle().addImages(bitmapHashMap);
+ mapboxMap.getStyle().addImagesAsync(bitmapHashMap);
}
}
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolLayerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolLayerActivity.java
index 244101746b..6eed142fc4 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolLayerActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolLayerActivity.java
@@ -9,7 +9,6 @@ import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.ViewGroup;
-
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.mapbox.geojson.Feature;
@@ -29,6 +28,7 @@ import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
import com.mapbox.mapboxsdk.style.sources.Source;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.utils.BitmapUtils;
+import timber.log.Timber;
import java.util.Arrays;
import java.util.List;
@@ -126,13 +126,21 @@ public class SymbolLayerActivity extends AppCompatActivity implements MapboxMap.
mapView.getMapAsync(this);
mapView.onCreate(savedInstanceState);
((ViewGroup) findViewById(R.id.container)).addView(mapView);
+
+ // Use OnStyleImageMissing API to lazily load an icon
+ mapView.addOnStyleImageMissingListener(id -> {
+ Style style = mapboxMap.getStyle();
+ if (style != null) {
+ Timber.e("Adding image with id: %s", id);
+ Bitmap androidIcon = BitmapUtils.getBitmapFromDrawable(getResources().getDrawable(R.drawable.ic_android_2));
+ style.addImage(id, Objects.requireNonNull(androidIcon));
+ }
+ });
}
@Override
public void onMapReady(@NonNull MapboxMap mapboxMap) {
this.mapboxMap = mapboxMap;
- // marker image
- Bitmap androidBitmap = BitmapUtils.getBitmapFromDrawable(getResources().getDrawable(R.drawable.ic_android_2));
Bitmap carBitmap = BitmapUtils.getBitmapFromDrawable(
getResources().getDrawable(R.drawable.ic_directions_car_black));
@@ -168,7 +176,6 @@ public class SymbolLayerActivity extends AppCompatActivity implements MapboxMap.
mapboxMap.setStyle(new Style.Builder()
.fromUrl("asset://streets.json")
- .withImage("Android", Objects.requireNonNull(androidBitmap), false)
.withImage("Car", Objects.requireNonNull(carBitmap), false)
.withSources(markerSource, mapboxSignSource)
.withLayers(markerSymbolLayer, mapboxSignSymbolLayer)
diff --git a/platform/android/src/android_renderer_frontend.cpp b/platform/android/src/android_renderer_frontend.cpp
index 21e8da6a21..6d235abe9f 100644
--- a/platform/android/src/android_renderer_frontend.cpp
+++ b/platform/android/src/android_renderer_frontend.cpp
@@ -50,6 +50,10 @@ public:
delegate.invoke(&RendererObserver::onDidFinishRenderingMap);
}
+ void onStyleImageMissing(const std::string& id, StyleImageMissingCallback done) override {
+ delegate.invoke(&RendererObserver::onStyleImageMissing, id, done);
+ }
+
private:
std::shared_ptr<Mailbox> mailbox;
ActorRef<RendererObserver> delegate;
diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp
index e74e4c3bbc..8f1ec9c576 100755
--- a/platform/android/src/native_map_view.cpp
+++ b/platform/android/src/native_map_view.cpp
@@ -261,6 +261,18 @@ void NativeMapView::onSourceChanged(mbgl::style::Source& source) {
}
}
+void NativeMapView::onStyleImageMissing(const std::string& imageId) {
+ assert(vm != nullptr);
+
+ android::UniqueEnv _env = android::AttachEnv();
+ static auto& javaClass = jni::Class<NativeMapView>::Singleton(*_env);
+ static auto onStyleImageMissing = javaClass.GetMethod<void (jni::String)>(*_env, "onStyleImageMissing");
+ auto weakReference = javaPeer.get(*_env);
+ if (weakReference) {
+ weakReference.Call(*_env, onStyleImageMissing, jni::Make<jni::String>(*_env, imageId));
+ }
+}
+
// JNI Methods //
void NativeMapView::resizeView(jni::JNIEnv&, int w, int h) {
diff --git a/platform/android/src/native_map_view.hpp b/platform/android/src/native_map_view.hpp
index 903543e5d1..c9ba6089c3 100755
--- a/platform/android/src/native_map_view.hpp
+++ b/platform/android/src/native_map_view.hpp
@@ -69,6 +69,7 @@ public:
void onDidBecomeIdle() override;
void onDidFinishLoadingStyle() override;
void onSourceChanged(mbgl::style::Source&) override;
+ void onStyleImageMissing(const std::string&) override;
// JNI //