将更新的共享本机库(.so 文件)添加到 Android Studio 应用会导致 UnsatisfiedLinkError
Adding an updated shared native library (.so file) to an Android Studio app leads to an UnsatisfiedLinkError
我有一个用 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) [不工作] 删除所有内容,重新编译所有内容
只是删除所有内容,即:
- 我的模块的 .externalNativeBuild 文件夹
- 我的模块的构建文件夹
- 我的应用程序的构建文件夹
并重建一切,即:
- 构建 > 清理项目
- 构建 > 制作模块 "my module"
- 构建 > 刷新链接的 C++ 项目
- 构建 > 重建项目
但这仍然会导致同样的 UnsatisfiedLinkError
2) [不起作用] 更改 .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”文件并包含新文件
一个有效的 "solution" 是使用 refactor > rename 将旧的“.so”文件重命名为 "libthird_party_library_OLD.so" 然后使用标准名称 "libthird_party_library.so" 复制新的第三方库。但这当然不是一个很好的解决方案,因为旧的不需要的库将包含在 apk 中。
原来是在 android studio 中链接版本化共享库时出现问题。与 this question and as described here 类似。
问题是“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 仅包含apk 中以 .so 结尾的库(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)
希望对您有所帮助!
我有一个用 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) [不工作] 删除所有内容,重新编译所有内容
只是删除所有内容,即:
- 我的模块的 .externalNativeBuild 文件夹
- 我的模块的构建文件夹
- 我的应用程序的构建文件夹
并重建一切,即:
- 构建 > 清理项目
- 构建 > 制作模块 "my module"
- 构建 > 刷新链接的 C++ 项目
- 构建 > 重建项目
但这仍然会导致同样的 UnsatisfiedLinkError
2) [不起作用] 更改 .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”文件并包含新文件
一个有效的 "solution" 是使用 refactor > rename 将旧的“.so”文件重命名为 "libthird_party_library_OLD.so" 然后使用标准名称 "libthird_party_library.so" 复制新的第三方库。但这当然不是一个很好的解决方案,因为旧的不需要的库将包含在 apk 中。
原来是在 android studio 中链接版本化共享库时出现问题。与 this question and as described here 类似。
问题是“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 仅包含apk 中以 .so 结尾的库(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)
希望对您有所帮助!