我有一个使用 NDK 的应用程序,当我尝试 运行 它在某些手机上但在其他手机上时效果很好

I have an application, that uses the NDK, and it works perfect when I try to run it on some phones, but not on others

我的应用程序适用于 Nexus 5、摩托罗拉 Moto G4 和电视盒 sex Minix Neo-X9。 但是当我在 LG G5 或 LeEco Le2 上尝试 运行 它时,我遇到了以下问题:

06-28 14:24:14.869: E/AndroidRuntime(7264): FATAL EXCEPTION: main
06-28 14:24:14.869: E/AndroidRuntime(7264): Process: com.vidyo.vidyomod, PID: 7264
06-28 14:24:14.869: E/AndroidRuntime(7264): java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.vidyo.vidyomod-1/base.apk"],nativeLibraryDirectories=[/data/app/com.vidyo.vidyomod-1/lib/arm64, /data/app/com.vidyo.vidyomod-1/base.apk!/lib/arm64-v8a, /vendor/lib64, /system/lib64]]] couldn't find "libVidyoClientApp.so"
06-28 14:24:14.869: E/AndroidRuntime(7264):     at java.lang.Runtime.loadLibrary(Runtime.java:367)
06-28 14:24:14.869: E/AndroidRuntime(7264):     at java.lang.System.loadLibrary(System.java:1076)
06-28 14:24:14.869: E/AndroidRuntime(7264):     at com.vidyo.VidyoClientLib.LmiAndroidAppJni.<clinit>(LmiAndroidAppJni.java:692)
06-28 14:24:14.869: E/AndroidRuntime(7264):     at java.lang.Class.newInstance(Native Method)
06-28 14:24:14.869: E/AndroidRuntime(7264):     at android.app.Instrumentation.newApplication(Instrumentation.java:1001)
06-28 14:24:14.869: E/AndroidRuntime(7264):     at android.app.Instrumentation.newApplication(Instrumentation.java:986)
06-28 14:24:14.869: E/AndroidRuntime(7264):     at android.app.LoadedApk.makeApplication(LoadedApk.java:582)
06-28 14:24:14.869: E/AndroidRuntime(7264):     at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5116)
06-28 14:24:14.869: E/AndroidRuntime(7264):     at android.app.ActivityThread.-wrap2(ActivityThread.java)
06-28 14:24:14.869: E/AndroidRuntime(7264):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1628)
06-28 14:24:14.869: E/AndroidRuntime(7264):     at android.os.Handler.dispatchMessage(Handler.java:111)
06-28 14:24:14.869: E/AndroidRuntime(7264):     at android.os.Looper.loop(Looper.java:207)
06-28 14:24:14.869: E/AndroidRuntime(7264):     at android.app.ActivityThread.main(ActivityThread.java:5917)
06-28 14:24:14.869: E/AndroidRuntime(7264):     at java.lang.reflect.Method.invoke(Native Method)
06-28 14:24:14.869: E/AndroidRuntime(7264):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:888)
06-28 14:24:14.869: E/AndroidRuntime(7264):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:749)

代码是一样的,怎么会在 phone 上运行,而在另一个 phone 上运行呢? 我的意思是,它在某些方面完美地运行库,而在其他方面则不然。我测试过,例如 LeEco 是 6.00,Nexus 5 是 6.0.1。所以我认为这不是 Android OS 问题

在我的 jniLibs 文件夹中,我有这个: jniLibs->armeabi-v7a->libVidyoClientApp.so

我是否还需要像这样的文件夹:jniLibs->arm64-v8a -> libVidyoClientApp.so 或类似的文件夹? 因为这一行而询问:

/data/app/com.vidyo.vidyomod-1/base.apk!/lib/arm64-v8a, /vendor/lib64, /system/lib64]]] couldn't find "libVidyoClientApp.so"

在我的 build.gradle 我有这个:

sourceSets.main {
    jni.srcDirs = []
    jniLibs.srcDir 'src/main/libs'
}

显然问题是由同事添加的库引起的:

compile 'com.github.mmin18:realtimeblurview:1.1.0'

这个库也需要在 android defaultConfig 这个:

    renderscriptTargetApi 19
    renderscriptSupportModeEnabled true

由于某种原因,这导致库无法在某些手机上运行

对于 64 位设备(大多数现代手机和平板电脑),您应该提供 lib/arm64-v8a 或 none 中的所有库。如果没有 64 位库,系统将愉快地使用 lib/armeabi-v7a 中的 32 位版本。但是,即使只有一个 64 位库(通常来自某些 3rd 方 SDK),您的应用程序也会因 UnsatisfiedLinkError.

最简单的控制方法是为 ndb-buildusually in Application.mk file 设置 APP_ABI=armeabi-v7a

使用 Android Studio (不是你的情况,jni.srcDirs = [] 禁用 NDK 集成),gradle 覆盖它。您需要 abiFilters in android.defaultConfig.ndk block 或像这样:

android {
  defaultConfig {
    externalNativeBuild {
      cmake {
        abiFilters "armeabi-v7a"
      }
    }
  }
}

或者,您可以为 64 位编译所有库。对于一些繁重的计算任务,您可以毫不费力地获得显着的性能提升。在其他情况下,收益很小,但将 C++ 代码移植到 64 位可能是一项具有挑战性的工作。此外,这可能会显着增加 APK 的大小。如果您选择同时提供 32 位和 64 位版本的应用,建议 split the APK.

特别是对于渲染脚本,性能提升可能不会超过处理多个 ABI 的麻烦。请注意,即使您将目标 API 设置为低于 21,gradle 也会复制 64 位 RenderScript 库。