将更新的共享本机库(.so文件)添加到Android Studio应用程序会导致UnsatisfiedLinkError

时间:2018-01-29 09:25:19

标签: android android-studio shared-libraries

我使用Android Studio 3.0.1和compileSdkVersion 26编写的Android应用程序。此应用程序依赖于用本机代码(c ++)编写的模块。模块中的本机代码取决于第三方共享库(.so)文件。在Cmake文件中,使用标准方法包含此第三方库,例如:

add_library( my-module-lib

             SHARED

             src/main/cpp/file1.cpp
             src/main/cpp/file2.cpp )

add_library( libthird_party_library SHARED IMPORTED )
set_target_properties( libthird_party_library PROPERTIES IMPORTED_LOCATION ${pathToProject}/src/main/jniLibs/${ANDROID_ABI}/libthird_party_library.so)

target_link_libraries( my-module-lib libthird_party_library )

然后将我的模块作为依赖项添加到主应用程序,并使用以下命令加载本机代码:

System.loadLibrary("my-module-lib");

这一切都运行正常,但我需要更新第三方库。我认为这就像替换新的.so文件一样简单。但这导致了一个UnsatisfiedLinkError:

java.lang.UnsatisfiedLinkError: dlopen failed: library "libthird_party_library.so.2" not found
                                                                                          at java.lang.Runtime.loadLibrary0(Runtime.java:989)
                                                                                          at java.lang.System.loadLibrary(System.java:1567)

应该注意的是android现在搜索" .so.2"文件而不是" .so"文件。所以我认为由于某种原因旧的仍然包含在某个地方,并且由于名称冲突,新的一个被重命名为" *。2"。所以我试着摆脱它:

1)[not working]删除所有内容,重新编译所有内容

删除所有内容,即:

  • 我模块的.externalNativeBuild文件夹
  • 我模块的构建文件夹
  • 我的应用的构建文件夹

重建一切,即:

  • 构建>清洁项目
  • 构建>制作模块"我的模块"
  • 构建>刷新链接的C ++项目
  • 构建>重建项目

但这仍然导致相同的UnsatisfiedLinkError

2)[not working]更改.so文件的名称

将更新的库的名称更改为" libthird_party_library_NEW.so" 并更改cmake文件:

set_target_properties( libthird_party_library PROPERTIES IMPORTED_LOCATION ${pathToProject}/src/main/jniLibs/${ANDROID_ABI}/libthird_party_library_NEW.so)

相同错误

3)[工作,不是一个好的解决方案]重命名旧的" .so"文件并包含新的

一个"解决方案"哪个工作正在重命名旧的" .so"使用重构>的文件将重命名为" libthird_party_library_OLD.so" ,然后使用标准名称​​" libthird_party_library.so"复制新的第三方库。 。但这当然不是一个非常好的解决方案,因为旧的不需要的库将包含在apk中。

1 个答案:

答案 0 :(得分:0)

在android studio中链接版本化的共享库时,结果证明是个问题。与this questionhere中描述的类似。

问题是" libthird_party_library.so "的内部版本号实际上是" libthird_party_library.so.2 "。这可以通过在.so文件上运行linux下的objdump来找到,即:

objdump -p libthird_party_library.so | grep so

输出:

libthird_party_library.so:     file format elf64-little
  NEEDED               libm.so
  NEEDED               libc.so
  NEEDED               libdl.so
  SONAME               libthird_party_library.so.2
  required from libdl.so:
  required from libm.so:
  required from libc.so:

由于android看到的文件名是" libthird_party_library.so "和android尝试加载" libthird_party_library.so.2 "它显然无法找到所需的库。

解决方案

一个明显的解决方案是将文件名更改为" libthird_party_library.so.2 ",但这不起作用,因为android studio仅包含以结尾的库.so在apk(aaargh)。

解决方法是将内部版本号更改为" libthird_party_library_2.so ",将文件重命名为" libthird_party_library_2.so "并更改Cmake文件以反映此更改。

1)更改内部版本号可以在linux下使用:

完成
rpl -R -e libthird_party_library.so.2 libthird_party_library_2.so libthird_party_library.so

第一个参数是内部版本号,第二个是我们需要将其更改为第三个参数,第三个参数是文件名。确定旧内部版本号的长度与新的一样!!

2)将文件名更改为" libthird_party_library_2.so "使用您最喜欢的工具

3)将CMake文件中的这一行改为

set_target_properties( libthird_party_library PROPERTIES IMPORTED_LOCATION ${pathToProject}/src/main/jniLibs/${ANDROID_ABI}/libthird_party_library_2.so)

希望这有帮助!