Android native library (.so) - unsatisfied link error

buk*_*.wh 1 c java-native-interface android kotlin

I have recently created and published an Android App bundle with compiled native libraries for all processors architectures. On most of devices everything is running ok. But on some of devices I can see this error in Crashlytics console Fatal Exception: java.lang.UnsatisfiedLinkError dalvik.system.PathClassLoader[DexPathList[[zip file "/system/framework/org.apache.http.legacy.boot.jar", zip file "/data/app/com.someapp-wAu5DoLmLvM_RVnbU1qsCg==/base.apk"],nativeLibraryDirectories=[/data/app/com.someapp-wAu5DoLmLvM_RVnbU1qsCg==/lib/arm64, /system/lib64]]] couldn't find "somemylib.so"

I am wondering - why this may happen. I have libs for x64 processors. This is happening only on some devices - but this crash is the most often in Crashlytics. All my libs are stored inside jniLibs directory THese are some pieces from my build.gradle

bundle {
    density {
        // Different APKs are generated for devices with different screen densities; true by default.
        enableSplit false
    }
    abi {
        // Different APKs are generated for devices with different CPU architectures; true by default.
        enableSplit true
    }
    language {
        // This is disabled so that the App Bundle does NOT split the APK for each language.
        // We're gonna use the same APK for all languages.
        enableSplit false
    }
}
splits {
    abi {
        enable true
        reset()
        include 'armeabi', 'mips', 'x86', 'armeabi-v7a', 'arm64-v8a', 
 'mips64', 'x86_64'
    }
}
sourceSets {

    main {
        jniLibs.srcDirs = ['jniLibs']
    }
}
Run Code Online (Sandbox Code Playgroud)

I have a service class inside my app which is trying to load native library when someone is starting it. My be sometimes this "start" call to service is executing before the OS can detect the native libs in my app? But I don't think that this is so. Can you help me please

Dan*_*nai 5

您的问题不是库代码,而是.so文件本身。Android设备具有主要的ABI,即处理器支持的指令集。例如,某些具有64位处理器的设备使用ABI arm64-v8a

但是,许多库和应用程序尚不支持64位处理器。因此,通常情况下,较新的处理器还支持辅助ABI,这是较常见的辅助ABI。例如,arm64-v8a处理器通常也支持armeabi-v7a

应用启动时,它将开始在目录中查找本机库。首先,arm64-v8a在此示例中,它签入主ABI目录。如果.so文件不存在,它将检入辅助ABI目录(armeabi-v7a)。如果仍然找不到,您将得到您描述的错误。

就您而言,如您所说,您拥有文件,所以这不是问题。

这种选择的一个大问题是,如果目录存在,它将始终坚持主ABI。如果并非所有库都为所有ABI提供所有.so文件,则可能导致崩溃。这在这里描述。

这是一个示例:您的应用程序中包含2个库:1. VideoPlayerLibrary,对于所有ABI都具有.so文件; 2。GifLibrary,对于armeabi和仅具有.so文件armeabi-v7a

现在,如果您在arm64-v8a设备上启动该应用程序,它将继续使用它的主要ABI,因为它已在其中找到文件(VideoPlayerLibrary的.so文件)。但是目前,您想播放gif文件,它将尝试从arm64-v8a目录中加载.so文件,但在该目录中找不到它们,并且将崩溃,如链接中所述。

所以,你可以做什么?

您有2个选择:

  1. 如果是您自己的库缺少.so文件,请为所有ABI对其进行编译。如果不是您自己的,请检查是否有较新的版本已解决此问题。
  2. 从应用程序中排除不完整的ABI。这样,较新的处理器将使用辅助ABI来运行该应用程序。当然,这将导致性能下降,但不会崩溃。根据我的经验,最重要的ABI是armeabi-v7a,可能所有Android设备都支持此功能。