[android] - add style image missing binding integration, add synchronous

image overloads to style
This commit is contained in:
tobrun
2019-04-04 11:09:28 +02:00
committed by Tobrun
parent a209714112
commit 0ac95bd994
10 changed files with 303 additions and 60 deletions

View File

@@ -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();
}
}

View File

@@ -568,7 +568,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);
}
@@ -577,7 +577,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);
}
@@ -586,7 +586,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);
}
@@ -595,7 +595,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);
}
@@ -604,7 +604,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);
}
@@ -613,7 +613,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);
}
@@ -622,7 +622,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);
}
@@ -631,7 +631,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);
}
@@ -640,7 +640,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);
}
@@ -649,7 +649,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);
}
@@ -658,7 +658,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);
}
@@ -667,7 +667,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);
}
@@ -676,7 +676,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);
}
@@ -685,7 +685,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);
}
@@ -694,7 +694,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);
}
@@ -703,7 +703,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);
}
@@ -712,7 +712,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);
}
@@ -721,7 +721,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);
}
@@ -730,7 +730,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);
}
@@ -748,7 +748,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);
}
@@ -757,7 +757,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);
}
@@ -767,7 +767,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);
}
@@ -776,7 +776,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);
}
@@ -785,7 +785,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);
}
@@ -794,10 +794,28 @@ 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>
@@ -976,6 +994,21 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
void onSourceChangedListener(String id);
}
/**
* 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.
*

View File

@@ -1025,7 +1025,9 @@ final class NativeMapView implements NativeMap {
@Keep
private void onDidBecomeIdle() {
stateCallback.onDidBecomeIdle();
if (stateCallback != null) {
stateCallback.onDidBecomeIdle();
}
}
@Keep
@@ -1042,6 +1044,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")) {
@@ -1473,5 +1483,7 @@ final class NativeMapView implements NativeMap {
void onDidBecomeIdle();
void onSourceChanged(String sourceId);
void onStyleImageMissing(String imageId);
}
}

View File

@@ -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);
}
}
}

View File

@@ -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"
}
}]
}
"""
}
}

View File

@@ -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);
}
}
}

View File

@@ -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)

View File

@@ -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;

View File

@@ -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) {

View File

@@ -69,6 +69,7 @@ public:
void onDidBecomeIdle() override;
void onDidFinishLoadingStyle() override;
void onSourceChanged(mbgl::style::Source&) override;
void onStyleImageMissing(const std::string&) override;
// JNI //