【问题标题】:Using a prebuilt shared Library in Android Studio (cmake)在 Android Studio (cmake) 中使用预构建的共享库
【发布时间】:2018-04-22 11:37:51
【问题描述】:

我想在我的 Android 应用程序中使用 C++ 共享库。 我尝试按照 Google 的 NDK 示例中的 hello-libs 示例进行操作,但不知何故没有成功。

看来,我的库没有打包到 APK 中。我找到的所有教程都使用*.mk-files,但我想使用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)

似乎在设备上找不到该库。否则看起来图书馆的路径仍然是我本地机器上的路径。

【问题讨论】:

  • dlopen("/data/app/my.package.name-1/lib/arm/libnative-lib.so", RTLD_LAZY) 你构建了那个目录吗?不应该是lib/armeabi-v7a吗?
  • @DanAlbert, no: 在设备上@9​​87654329@ 下的有效路径是 arm, arm64, x86, x86_64。不要问我为什么。
  • @aydinugur 你能解决这个问题吗?我有同样的问题,但不知道如何解决它..

标签: android c++ android-ndk android-gradle-plugin android-studio-3.0


【解决方案1】:

预建的 libLibrary.so 没有 SONAME。如果由于某种原因您无法使用最新的 NDK 重建此库,您可以尝试使用 patchelf 实用程序将 SONAME 添加到现有二进制文件中。

【讨论】:

    【解决方案2】:

    要将预构建的库打包到您的 APK 中,您需要使用 sourceSets 块手动配置 Gradle,以包含 .so 文件的路径。构建 APK 后,您可以使用 APK Analyzer(Build>Analyze APK...) 验证 Gradle 将哪些库打包到您的 APK 中。

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

    更多信息请看这里“Include prebuilt native libraries

    【讨论】:

      【解决方案3】:

      您无需使用 CMake 即可使用共享库(.so 文件)。只需将库放在src/main/jniLibs 目录中的相应目录中即可。然后就可以直接加载库了。

      Android Studio 可能会在本机方法声明中显示错误,但您的应用会正常运行。

      【讨论】:

      • 但是如何使用我的native-lib-cpp 中的库?共享库没有 jni 方法,我想将它们包装在第二个库中,在 Android Studio 中编写。
      • 你仍然可以从 jniLibs 文件夹中 target_link_libraries 它,只需指定目录
      • @DmitriiZ。你能分享一下 target_link_libraries 的确切参数吗?
      【解决方案4】:

      另一种将预建库打包到 APK 中的解决方案 - 将它们链接到 jniLibs。

      例如,我不使用库的直接放置(因为它们已经存在于其他地方 - 在我的情况下,在 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
          .
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-30
        • 1970-01-01
        • 2015-08-18
        • 1970-01-01
        • 1970-01-01
        • 2011-09-04
        相关资源
        最近更新 更多