mapbox-maps-android icon indicating copy to clipboard operation
mapbox-maps-android copied to clipboard

conflict issue occurs because the libc++_shared.so versions

Open SeoMyungjun opened this issue 1 year ago • 8 comments

Environment

  • Android OS version: 14
  • Devices affected: galaxy S22+ samsung
  • Maps SDK Version: 11.0.0 and 11.1.0

Observed behavior and steps to reproduce

It is used by adding a 3dr party library called ZTA_release in a multi-module environment. It appears that a conflict issue occurs because the libc++_shared.so versions of ZTA lib and Mapbox's common-24.1.0 library are different.

2 files found with path 'lib/arm64-v8a/libc++_shared.so' from inputs:

  • /Users/smj/.gradle/caches/transforms-3/8a5c0298a03bd21724b03309be68e201/transformed/ZTA_release/jni/arm64-v8a/libc++_shared.so
  • /Users/smj/.gradle/caches/transforms-3/785aa80556add9db0dba40a83d4139cf/transformed/common-24.1.0/jni/arm64-v8a/libc++_shared.so If you are using jniLibs and CMake IMPORTED targets, see

So I tried one method. packagingOptions { pickFirst '/armeabi-v7a/libc++_shared.so' pickFirst '/arm64-v8a/libc++_shared.so' }

However, the following issue occurs. ATAL EXCEPTION: main Process: com.routo.mapsdkapp, PID: 30708 java.lang.UnsatisfiedLinkError: No implementation found for java.lang.String com.mapbox.common.MapboxOptionsImpl.getAccessToken() (tried Java_com_mapbox_common_MapboxOptionsImpl_getAccessToken and Java_com_mapbox_common_MapboxOptionsImpl_getAccessToken__) - is the library loaded, e.g. System.loadLibrary? at com.mapbox.common.MapboxOptionsImpl.getAccessToken(Native Method) at com.mapbox.common.MapboxOptions.getAccessToken(MapboxOptions.kt:17) at com.mapbox.maps.MapController.(MapController.kt:70) at com.mapbox.maps.MapView.(MapView.kt:109) at com.mapbox.maps.MapView.(MapView.kt:59) at com.routo.mapsdk.RoutoMap.(RoutoMap.kt:196) at com.routo.mapsdk.RoutoMap.(RoutoMap.kt:196) at com.routo.mapsdkapp.ExampleOverviewActivity.onCreate(ExampleOverviewActivity.kt:52) at android.app.Activity.performCreate(Activity.java:8944) at android.app.Activity.performCreate(Activity.java:8913) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1456) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4146) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4322) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:139) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:96) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2685) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loopOnce(Looper.java:230) at android.os.Looper.loop(Looper.java:319) at android.app.ActivityThread.main(ActivityThread.java:8893) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:608) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103)

Expected behavior

Notes / preliminary analysis

Additional links and references

SeoMyungjun avatar Feb 08 '24 07:02 SeoMyungjun

@SeoMyungjun hi! The workaround you added should work in general, again if the libc++ binaries are both compatible with each other. The build issue you see does not mean incompatible libc++ is used, gradle fails if more then one libc++ are provided by the dependencies, even if they are of same or compatible version.

Process: com.routo.mapsdkapp, PID: 30708
java.lang.UnsatisfiedLinkError: No implementation found for java.lang.String com.mapbox.common.MapboxOptionsImpl.getAccessToken()

means that our internal library function is not available in the native module. How do you integrate Mapbox dependencies, could you provide build.gradle config with it?

PS. More details on libc++ compatibility. If the ZTA_release lib contains libc++ it is indeed should be compatible with the libc++ that is provided in Maps. We build our libs with NDK 23 at the moment hence ZTA_release lib should be also built with the same or more recent version as there is a known issue that NDK 22/23 are not compatible.

yunikkk avatar Feb 08 '24 12:02 yunikkk

In addition to @yunikkk 's comment above explicitly noting that Maps v11 are built with NDK 23 while Maps v10 are built with NDK 21 so it may be an option for you to use Maps v10.

kiryldz avatar Feb 12 '24 13:02 kiryldz

@yunikkk here is my build.gradle config I need to use v11 or higher.

image

dependencies {

implementation(project(":mapsdk"))
implementation fileTree(dir: 'libs', include: ['*.aar'])
implementation "androidx.startup:startup-runtime:1.1.1"

implementation 'androidx.core:core-ktx:1.8.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
implementation "androidx.work:work-runtime-ktx:2.8.1" // kotlin
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.recyclerview:recyclerview:1.3.1'
implementation 'com.google.android.material:material:1.9.0'
implementation 'androidx.asynclayoutinflater:asynclayoutinflater:1.0.0'

testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'

// // retrofit2 implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0' // okhttp3 implementation 'com.squareup.okhttp3:okhttp:4.10.0' implementation 'com.squareup.okhttp3:logging-interceptor:4.9.0'

implementation("com.mapbox.maps:android:11.1.0")

//add
implementation 'com.mapbox.mapboxsdk:mapbox-sdk-turf:5.4.1'

// implementation 'com.mapbox.mapboxsdk:mapbox-sdk-geojson:6.9.0' implementation 'com.mapbox.mapboxsdk:mapbox-sdk-services:5.4.1'

implementation 'androidx.multidex:multidex:2.0.1'

implementation 'com.fasterxml.jackson.core:jackson-databind:2.12.3'

}

android { packagingOptions {

// pickFirst 'lib/x86/libc++_shared.so' // pickFirst 'lib/x86_64/libc++_shared.so' pickFirst '/armeabi-v7a/libc++_shared.so' pickFirst '/arm64-v8a/libc++_shared.so' resources { exclude 'META-INF/NOTICE.md' exclude 'META-INF/LICENSE.md' excludes += '/META-INF/{AL2.0,LGPL2.1}' } } }

SeoMyungjun avatar Feb 14 '24 04:02 SeoMyungjun

@SeoMyungjun few additional questions :

  • the gradle entries
implementation("com.mapbox.maps:android:11.1.0")
implementation 'com.mapbox.mapboxsdk:mapbox-sdk-turf:5.4.1'
// implementation 'com.mapbox.mapboxsdk:mapbox-sdk-geojson:6.9.0'
implementation 'com.mapbox.mapboxsdk:mapbox-sdk-services:5.4.1'

is the only place where mapbox dependencies are being added, correct? No local aars are present in the project?

  • do you somehow configure androidx.startup.InitializationProvider maybe? Could you check the merged manifest (typically lives in app/build/intermediates/merged_manifest/debug/AndroidManifest.xml) to see how it is configured? Merged manifest should contain provider config e.g. :
...
        <provider
            android:name="androidx.startup.InitializationProvider"
...
        </provider>
...

)

yunikkk avatar Feb 14 '24 15:02 yunikkk

@yunikkk I tried provider but I'm not using it right now.

<!--        <provider-->
<!--            android:name="androidx.startup.InitializationProvider"-->
<!--            android:authorities="${applicationId}.androidx-startup"-->
<!--            tools:node="remove">-->
<!--        </provider>-->

<!--        <provider-->
<!--            android:name="androidx.startup.InitializationProvider"-->
<!--            android:authorities="${applicationId}.androidx-startup"-->
<!--            android:exported="false"-->
<!--            tools:node="merge">-->
<!--            <meta-data-->
<!--                android:name="com.mapbox.maps.loader.MapboxMapsInitializer"-->
<!--                android:value="androidx.startup"-->
<!--                tools:node="remove" />-->
<!--        </provider>-->

SeoMyungjun avatar Feb 15 '24 01:02 SeoMyungjun

Okay, but Maps has it's own provider and it should be added to the merged manifest, otherwise native libraries will not be loaded. Could you check the merged manifest provider entries?

yunikkk avatar Feb 15 '24 09:02 yunikkk

@yunikkk here is AndroidManifest.xml (app/build/intermediates/merged_manifest/debug/AndroidManifest.xml)

<provider
            android:name="androidx.startup.InitializationProvider"
            android:authorities="com.routo.mapsdkapp.androidx-startup"
            android:exported="false" >
            <meta-data
                android:name="com.mapbox.maps.loader.MapboxMapsInitializer"
                android:value="androidx.startup" />
            <!-- This entry makes MapboxSDKCommonInitializer discoverable. -->
            <meta-data
                android:name="com.mapbox.common.MapboxSDKCommonInitializer"
                android:value="androidx.startup" />
            <meta-data
                android:name="androidx.work.WorkManagerInitializer"
                android:value="androidx.startup" />
            <meta-data
                android:name="androidx.emoji2.text.EmojiCompatInitializer"
                android:value="androidx.startup" />
            <meta-data
                android:name="androidx.lifecycle.ProcessLifecycleInitializer"
                android:value="androidx.startup" />
        </provider>

        <receiver
            android:name="com.mapbox.common.location.LocationUpdatesReceiver"
            android:enabled="true"
            android:exported="false" >
            <intent-filter>
                <action android:name="com.mapbox.common.location.LocationUpdatesReceiver.ACTION_PROCESS_LOCATION_UPDATES" />
            </intent-filter>
        </receiver>

        <service
            android:name="com.mapbox.common.LifecycleService"
            android:exported="false" /> <!-- Needs to be explicitly declared on P+ -->
        

SeoMyungjun avatar Feb 20 '24 04:02 SeoMyungjun

@SeoMyungjun ok, both MapboxSDKCommonInitializer and MapboxMapsInitializer are there so this means native libraries should load, when those initializers are triggered. I see couple possible reasons here :

  • mapbox-common native lib was not bundled in the build for some reason. You could check in the Android Studio - open the built APK and you should see lib/YOUR_ABI/ both libmapbox-maps.so / libmapbox-common.so there
  • initializers were not launched. Which should be fine since you have them in the manifest. Could you share the full logcat when this crash happens to double check?

yunikkk avatar Feb 20 '24 09:02 yunikkk