我想在我的Android App中使用C ++共享库。
我尝试按照Google的NDK示例中的hello-libs
示例进行操作,但不管怎么说它都没有用完。
看来,我的图书馆并没有打包到APK中。我找到的所有教程都使用*.mk
- 文件,但我想使用cmake
。
这是我的CMakeLists.txt:
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
# native lib
add_library(native-lib SHARED
native-lib.cpp)
set(IMPORT_DIR ${CMAKE_SOURCE_DIR}/../jniLibs)
# shared lib
add_library(shared-lib SHARED IMPORTED)
set_target_properties(shared-lib PROPERTIES IMPORTED_LOCATION
${IMPORT_DIR}/dynamic/lib/${ANDROID_ABI}/libLibrary.so)
target_include_directories(native-lib PRIVATE
${IMPORT_DIR}/dynamic/include)
# linking libs
target_link_libraries(native-lib
android
shared-lib
log)
我将shared-lib
与其他人一起关联后,运行该应用时出现以下错误:
E/art: dlopen("/data/app/my.package.name-1/lib/arm/libnative-lib.so", RTLD_LAZY) failed: dlopen failed: library "C:/projects/HelloLibs/app/src/main/cpp/../jniLibs/dynamic/lib/armeabi-v7a/libLibrary.so" not foun
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: my.package.name, PID: 29266
java.lang.UnsatisfiedLinkError: dlopen failed: library "C:/projects/HelloLibs/app/src/main/cpp/../jniLibs/dynamic/lib/armeabi-v7a/libLibrary.so" not found
at java.lang.Runtime.loadLibrary(Runtime.java:371)
at java.lang.System.loadLibrary(System.java:988)
at my.package.name.MainActivity.<clinit>(MainActivity.java:11)
at java.lang.reflect.Constructor.newInstance(Native Method)
at java.lang.Class.newInstance(Class.java:1690)
at android.app.Instrumentation.newActivity(Instrumentation.java:1078)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2543)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2771)
at android.app.ActivityThread.access$900(ActivityThread.java:177)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1432)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5912)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1405)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1200)
看起来设备上找不到该库。否则看起来图书馆的路径仍然是我当地机器上的路径。
答案 0 :(得分:3)
预建的 libLibrary.so 没有SONAME。如果由于某种原因您无法使用最新的NDK重建此库,您可以尝试使用patchelf实用程序将SONAME添加到现有二进制文件。
答案 1 :(得分:1)
要将预建的库打包到您的APK中,您需要使用 sourceSets 块手动配置Gradle以包括.so文件的路径。生成APK后,您可以使用APK分析器(Build> Analyze APK ...)来验证Gradle将哪些库打包到您的APK中。
android {
...
sourceSets {
main {
jniLibs.srcDirs 'imported-lib/src/', 'more-imported-libs/src/'
}
}
有关更多信息,请在此处查看“ Include prebuilt native libraries”
答案 2 :(得分:0)
您不需要使用CMake来使用共享库(.so文件)。只需将库放在src/main/jniLibs
目录中的相应目录中即可。然后你可以直接加载库。
Android Studio可能会在本机方法声明中显示错误,但是,您的应用程序可以正常工作。
答案 3 :(得分:0)
将预构建库打包到APK中的另一种解决方案-将它们链接到jniLib。
例如,我不使用库的直接放置(因为它们已经存在于其他地方-在我的情况下,在Docker映像中具有所有必需的预构建,SDK,NDK等),但我只使用链接到它们将它们放入APK。而且,如果在构建时也需要此类库,则cmake可以简单地使用find_package()。
/app/src/main$ tree
.
├── jniLibs
│ ├── arm64-v8a
│ │ ├── libCommonAPI.so -> /opt/thirdparty/android-29/arm64-v8a/capicxx-core-runtime/lib/libCommonAPI.so
│ │ ├── libCommonAPI-SomeIP.so -> /opt/thirdparty/android-29/arm64-v8a/capicxx-someip-runtime/lib/libCommonAPI-SomeIP.so
│ │ ├── libvsomeip3-cfg.so -> /opt/thirdparty/android-29/arm64-v8a/vsomeip/lib/libvsomeip3-cfg.so
│ │ ├── libvsomeip3-e2e.so -> /opt/thirdparty/android-29/arm64-v8a/vsomeip/lib/libvsomeip3-e2e.so
│ │ ├── libvsomeip3-sd.so -> /opt/thirdparty/android-29/arm64-v8a/vsomeip/lib/libvsomeip3-sd.so
│ │ └── libvsomeip3.so -> /opt/thirdparty/android-29/arm64-v8a/vsomeip/lib/libvsomeip3.so
│ ├── armeabi-v7a
│ │ ├── libCommonAPI.so -> /opt/thirdparty/android-29/armeabi-v7a/capicxx-core-runtime/lib/libCommonAPI.so
│ │ ├── libCommonAPI-SomeIP.so -> /opt/thirdparty/android-29/armeabi-v7a/capicxx-someip-runtime/lib/libCommonAPI-SomeIP.so
│ │ ├── libvsomeip3-cfg.so -> /opt/thirdparty/android-29/armeabi-v7a/vsomeip/lib/libvsomeip3-cfg.so
│ │ ├── libvsomeip3-e2e.so -> /opt/thirdparty/android-29/armeabi-v7a/vsomeip/lib/libvsomeip3-e2e.so
│ │ ├── libvsomeip3-sd.so -> /opt/thirdparty/android-29/armeabi-v7a/vsomeip/lib/libvsomeip3-sd.so
│ │ └── libvsomeip3.so -> /opt/thirdparty/android-29/armeabi-v7a/vsomeip/lib/libvsomeip3.so
│ ├── x86
│ │ ├── libCommonAPI.so -> /opt/thirdparty/android-29/x86/capicxx-core-runtime/lib/libCommonAPI.so
│ │ ├── libCommonAPI-SomeIP.so -> /opt/thirdparty/android-29/x86/capicxx-someip-runtime/lib/libCommonAPI-SomeIP.so
│ │ ├── libvsomeip3-cfg.so -> /opt/thirdparty/android-29/x86/vsomeip/lib/libvsomeip3-cfg.so
│ │ ├── libvsomeip3-e2e.so -> /opt/thirdparty/android-29/x86/vsomeip/lib/libvsomeip3-e2e.so
│ │ ├── libvsomeip3-sd.so -> /opt/thirdparty/android-29/x86/vsomeip/lib/libvsomeip3-sd.so
│ │ └── libvsomeip3.so -> /opt/thirdparty/android-29/x86/vsomeip/lib/libvsomeip3.so
│ └── x86_64
│ ├── libCommonAPI.so -> /opt/thirdparty/android-29/x86_64/capicxx-core-runtime/lib/libCommonAPI.so
│ ├── libCommonAPI-SomeIP.so -> /opt/thirdparty/android-29/x86_64/capicxx-someip-runtime/lib/libCommonAPI-SomeIP.so
│ ├── libvsomeip3-cfg.so -> /opt/thirdparty/android-29/x86_64/vsomeip/lib/libvsomeip3-cfg.so
│ ├── libvsomeip3-e2e.so -> /opt/thirdparty/android-29/x86_64/vsomeip/lib/libvsomeip3-e2e.so
│ ├── libvsomeip3-sd.so -> /opt/thirdparty/android-29/x86_64/vsomeip/lib/libvsomeip3-sd.so
│ └── libvsomeip3.so -> /opt/thirdparty/android-29/x86_64/vsomeip/lib/libvsomeip3.so
.