一起使用 JavaCV 和 Realm 会导致 "java.lang.UnsatisfiedLinkError"

Using JavaCV and Realm together causes "java.lang.UnsatisfiedLinkError"

我最近在尝试启动 JavaCV 的 FFmpegFrameGrabber 实例时遇到以下错误:

java.lang.UnsatisfiedLinkError: org.bytedeco.javacpp.avutil
    at java.lang.Class.classForName(Native Method)
    at java.lang.Class.forName(Class.java:324)
    at org.bytedeco.javacpp.Loader.load(Loader.java:413)
    at org.bytedeco.javacpp.Loader.load(Loader.java:381)
    at org.bytedeco.javacpp.avformat$AVFormatContext.<clinit>(avformat.java:2597)
    at org.bytedeco.javacv.FFmpegFrameGrabber.startUnsafe(FFmpegFrameGrabber.java:386)
    at org.bytedeco.javacv.FFmpegFrameGrabber.start(FFmpegFrameGrabber.java:380)...

虽然存在解决此问题的方法,但 none 对我有用。

通过多次试验我发现奇怪的是,如果我在我的项目中不包含 Realm,我将不再收到此错误。

这是我的 build.gradle 文件的一部分,其中包含所有这些库:

compile group: 'org.bytedeco', name: 'javacv', version: '1.1'
compile group: 'org.bytedeco.javacpp-presets', name: 'opencv', version: '3.0.0-1.1', classifier: 'android-arm'
compile group: 'org.bytedeco.javacpp-presets', name: 'opencv', version: '3.0.0-1.1', classifier: 'android-x86'
compile group: 'org.bytedeco.javacpp-presets', name: 'ffmpeg', version: '2.8.1-1.1', classifier: 'android-arm'
compile group: 'org.bytedeco.javacpp-presets', name: 'ffmpeg', version: '2.8.1-1.1', classifier: 'android-x86'

// ORM
compile 'io.realm:realm-android:0.87.2' // Tested NOT OK - Causes JavaCV to crash
//

我在想这个问题可能有一个我不知道的解决方案。我发现互联网上没有任何地方提到库不兼容或为什么会出现这种行为。

我将使用任何人可能需要的任何其他详细信息编辑此 post。

如有任何帮助,我们将不胜感激。

编辑

我尝试应用 here 中描述的修复。 现在我的包装选项如下所示:

packagingOptions {
    exclude 'META-INF/LICENSE.txt'
    exclude 'META-INF/NOTICE.txt'
    exclude 'META-INF/maven/org.bytedeco.javacpp-presets/ffmpeg/pom.properties'
    exclude 'META-INF/maven/org.bytedeco.javacpp-presets/ffmpeg/pom.xml'
    exclude 'META-INF/maven/org.bytedeco.javacpp-presets/opencv/pom.properties'
    exclude 'META-INF/maven/org.bytedeco.javacpp-presets/opencv/pom.xml'

    exclude "lib/arm64-v8a/librealm-jni.so"
}

很遗憾,此更改没有效果。我还是卡住了。

在我一位同事的帮助下,我已经能够解决这个问题。

除了问题中描述的步骤,我们:

  • 复制了 app/src/main/jniLibs/armeabiapp/src/main/jniLibs/armeabi-v7a 文件夹中的所有 .so 文件
  • 已添加

    ndk{ abi过滤器 "armeabi-v7a" }

    到模块 build.gradle 文件的 defaultConfig 部分

  • 已添加

    lint选项{ abortOnError 错误 }

    到模块 build.gradle 文件的 android 部分

如果可以的话,我会尽量向任何需要的人提供进一步的说明。

首先,这个问题的发生是因为 Gradle 没有从 maven 配置文件中正确解析依赖项。在我的例子中,只有 x86 依赖项传送到 APK。这意味着上面的代码仅适用于 x86 cpu 架构。解决方案应该在 Android Studio 上完成。但作为解决方法,我这样做了:

  1. 下载二进制文件javacv-platform-1.3.1-bin.zip. It's from: https://github.com/bytedeco/javacv
  2. 内部目录javacv-bin将这些jar复制到新目录

    1. ffmpeg-android-arm.jar
    2. opencv-android-arm.jar
    3. ffmpeg-android-x86.jar
    4. opencv-android-x86.jar
  3. 对于 2.1 2.2 文件,提取这些 jar 并转到 lib 然后或 armeabi。然后将所有 *.so 文件复制到您的项目中:

    1. app/src/main/jniLibs/armeabi/
    2. app/src/main/jniLibs/armeabi-v7a/
  4. 您可以通过将依赖项复制到 app/src/main/jniLibs/x86/ 来对 2.3 * 2.4 jar 执行相同的操作。如果确实没有,请检查您的 apk

就是这样。