maplibre / maplibre-native

MapLibre Native - Interactive vector tile maps for iOS, Android and other platforms.
https://maplibre.org
BSD 2-Clause "Simplified" License
1.03k stars 299 forks source link

Snapshotter crashes when passing style as String on Android #903

Open fynngodau opened 1 year ago

fynngodau commented 1 year ago

Describe the bug

When using Snapshotter together with a Style.Builder constructed using fromJson(String), the app crashes with the expection seen below.

Expected behavior

Let assets/basic-style.json be a valid style.

The following works – on a normal map:

diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/SimpleMapActivity.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/SimpleMapActivity.kt
index 819527ab3..939690f0a 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/SimpleMapActivity.kt
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/SimpleMapActivity.kt
@@ -22,7 +22,9 @@ class SimpleMapActivity : AppCompatActivity() {
                 val styles = Style.getPredefinedStyles()
                 if (styles != null && styles.size > 0) {
                     val styleUrl = styles[0].url
-                    mapboxMap.setStyle(Style.Builder().fromUri(styleUrl))
+                    mapboxMap.setStyle(Style.Builder().fromJson(
+                            assets.open("basic-style.json").bufferedReader().readText()
+                    ))
                 }
             }
         )

Opening Simple map in the demo app works as expected.

To Reproduce

The following does not work:

diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterActivity.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterActivity.kt
index 404e61083..6dac47764 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterActivity.kt
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterActivity.kt
@@ -67,15 +67,9 @@ class MapSnapshotterActivity : AppCompatActivity() {
     private fun startSnapShot(row: Int, column: Int) {
         // Optionally the style
         val builder = Style.Builder()
-            .fromUri(
-                Style.getPredefinedStyle(
-                    if ((column + row) % 2 == 0) {
-                        "Streets"
-                    } else {
-                        "Pastel"
-                    }
+                .fromJson(
+                        assets.open("basic-style.json").bufferedReader().readText()
                 )
-            )

         // Define the dimensions
         val options = MapSnapshotter.Options(

The app crashes with the following exception once the Map Snapshotter demo is opened in the sample app:

2023-03-15 19:51:02.164  7671-7671  AndroidRuntime          com.mapbox.mapboxsdk.testapp         E  FATAL EXCEPTION: main
                                                                                                    Process: com.mapbox.mapboxsdk.testapp, PID: 7671
                                                                                                    java.lang.IllegalStateException: invalid native peer
                                                                                                        at com.mapbox.mapboxsdk.snapshotter.MapSnapshotter.nativeAddSource(Native Method)
                                                                                                        at com.mapbox.mapboxsdk.snapshotter.MapSnapshotter.onDidFinishLoadingStyle(MapSnapshotter.kt:656)
                                                                                                        at com.mapbox.mapboxsdk.snapshotter.MapSnapshotter.nativeInitialize(Native Method)
                                                                                                        at com.mapbox.mapboxsdk.snapshotter.MapSnapshotter.<init>(MapSnapshotter.kt:328)
                                                                                                        at com.mapbox.mapboxsdk.testapp.activity.snapshot.MapSnapshotterActivity.startSnapShot(MapSnapshotterActivity.kt:194)
                                                                                                        at com.mapbox.mapboxsdk.testapp.activity.snapshot.MapSnapshotterActivity.addSnapshots(MapSnapshotterActivity.kt:62)
                                                                                                        at com.mapbox.mapboxsdk.testapp.activity.snapshot.MapSnapshotterActivity.access$addSnapshots(MapSnapshotterActivity.kt:39)
                                                                                                        at com.mapbox.mapboxsdk.testapp.activity.snapshot.MapSnapshotterActivity$onCreate$1.onGlobalLayout(MapSnapshotterActivity.kt:53)
                                                                                                        at android.view.ViewTreeObserver.dispatchOnGlobalLayout(ViewTreeObserver.java:1148)
                                                                                                        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3426)
                                                                                                        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2328)
                                                                                                        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:9080)
                                                                                                        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1231)
                                                                                                        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1239)
                                                                                                        at android.view.Choreographer.doCallbacks(Choreographer.java:899)
                                                                                                        at android.view.Choreographer.doFrame(Choreographer.java:832)
                                                                                                        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1214)
                                                                                                        at android.os.Handler.handleCallback(Handler.java:942)
                                                                                                        at android.os.Handler.dispatchMessage(Handler.java:99)
                                                                                                        at android.os.Looper.loopOnce(Looper.java:201)
                                                                                                        at android.os.Looper.loop(Looper.java:288)
                                                                                                        at android.app.ActivityThread.main(ActivityThread.java:7872)
                                                                                                        at java.lang.reflect.Method.invoke(Native Method)
                                                                                                        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
                                                                                                        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)

Platform information (please complete the following information):

louwers commented 1 year ago

@fynngodau I am not a JNI expert. Do you know what invalid native peer means by any chance? Have you seen it before?

fynngodau commented 1 year ago

@louwers Unfortunately not, I also haven't had a look at the relevant native code so far.

ovivoda commented 1 year ago

@fynngodau please share a branch where you have the commit. I will try to reproduce it on my side and see if I can figure it out.

fynngodau commented 1 year ago

@ovivoda Gladly! I created a branch with both changes (SimpleMapActivity modified but still working, MapSnapshotterActivity modified but broken) here: https://github.com/e-foundation/maplibre-gl-native/tree/demo-903-string-style-snapshotter-crash

ovivoda commented 1 year ago

@fynngodau I found a brute force fix for this but I think more investigation is needed to find the actual problem that probably comes from the native code!?

Here is a PR: https://github.com/maplibre/maplibre-gl-native/pull/941