在Android Studio(cmake)中使用预构建的共享库。

11 浏览
0 Comments

在Android Studio(cmake)中使用预构建的共享库。

我想在我的Android应用程序中使用一个C++共享库。

我尝试按照Google的NDK示例中的hello-libs示例进行,但不知何故无法成功。

看起来,我的库没有打包到APK中。我找到的所有教程都使用*.mk文件,但我想使用cmake

这是我的CMakeLists.txt文件:

# 设置构建本地库所需的CMake的最低版本。
cmake_minimum_required(VERSION 3.4.1)
# 本地库
add_library(native-lib SHARED
            native-lib.cpp)
set(IMPORT_DIR ${CMAKE_SOURCE_DIR}/../jniLibs)
# 共享库
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)
# 链接库
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.(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
0 Comments

问题原因:预构建的libLibrary.so库没有SONAME。

解决方法:如果由于某种原因无法使用最新的NDK重新构建该库,可以尝试使用patchelf工具向现有的二进制文件中添加SONAME。

0
0 Comments

问题的原因:在使用Android Studio进行开发时,如果想要将预构建的共享库打包到APK中,需要手动配置Gradle的sourceSets块,以包含.so文件的路径。这是因为Gradle默认不会自动包含预构建的共享库。

解决方法:在build.gradle文件中的android块中添加如下代码,将预构建共享库的路径包含进去。

android {
    ...
    sourceSets {
        main {
            jniLibs.srcDirs 'imported-lib/src/', 'more-imported-libs/src/'
        }
    }
}

通过使用APK Analyzer(Build> Analyze APK...),可以验证Gradle将哪些库打包到APK中。

详情请参见此处:Include prebuilt native libraries

0
0 Comments

问题的出现原因:用户想在Android Studio中使用一个预先构建的共享库(.so文件),但不知道如何将其加载到项目中。

解决方法:将共享库文件放置在src/main/jniLibs目录的相应目录中,然后可以直接加载库文件。即使Android Studio在本地方法声明中显示错误,但是应用程序仍然可以正常工作。

但是,用户想知道如何在native-lib-cpp中使用这个库。这个共享库没有jni方法,用户希望将其包装到在Android Studio中编写的第二个库中。

解决方法:仍然可以从jniLibs文件夹中使用target_link_libraries来链接它,只需要指定目录即可。但是用户想知道target_link_libraries的确切参数。

0