11

I want to use a C++ shared library inside my Android App. I tried to follow along the hello-libs example from Google's NDK samples, but somehow it doesn't work out.

It seems, that my library isn't packed into the APK. All tutorials i found are using *.mk-files, but I want to use cmake.

This is my 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)

As soon as I link the shared-lib along with the others, I get the following error, when running the app:

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)

It looks like the library is not found on the device. Otherwise it looks like the librarie's path is still the one on my local maschine.

aydinugur
  • 1,208
  • 2
  • 14
  • 21
Dario
  • 582
  • 1
  • 5
  • 17
  • `dlopen("/data/app/my.package.name-1/lib/arm/libnative-lib.so", RTLD_LAZY)` Did you construct that directory? Shouldn't it be `lib/armeabi-v7a`? – Dan Albert Nov 09 '17 at 18:55
  • @DanAlbert, no: on device the valid paths under `lib` are **arm**, **arm64**, **x86**, **x86_64**. Don't ask me why. – Alex Cohn Nov 09 '17 at 22:02
  • @aydinugur Were you able to solve this issue?? I am having the same problem but can't figure out how to solve it.. – Swati Garg Aug 28 '18 at 14:44
  • I got same problem with my own prebuilt, but with openssl prebuilt it working normal. Did you solve your issue? – MinhNV Feb 13 '22 at 11:56

4 Answers4

4

The prebuilt libLibrary.so does not have SONAME. If for whatever reason you cannot rebuild this library with latest NDK, you may try the patchelf utility to add SONAME to existing binary.

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
3

To package the prebuilt library into your APK, you need to manually configure Gradle with the sourceSets block to include the path to your .so file. After building your APK, you can verify which libraries Gradle packages into your APK by using the APK Analyzer(Build>Analyze APK...).

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

for more information please see here "Include prebuilt native libraries"

Ali Maddi
  • 309
  • 3
  • 8
1

You don't need to use CMake to use shared libraries (.so files). Just place the libraries inside the respective directories in src/main/jniLibs directory. Then you can load the libraries directly.

Android studio may show error in the native method declarations but, your app will work fine.

Nabin Bhandari
  • 15,949
  • 6
  • 45
  • 59
  • But how can I use the library inside my `native-lib-cpp`? The shared library has no jni-methods, I want to wrap them inside a second library, written inside Android Studio. – Dario Nov 09 '17 at 13:08
  • You can still target_link_libraries it from jniLibs folder, just specify directory – Dmitrii Z. Nov 09 '17 at 21:17
  • 1
    @DmitriiZ. can you please share the exact arguments of target_link_libraries? – nutella_eater Oct 13 '20 at 21:43
0

Another solution for packing the prebuilt libraries into your APK - linking them to jniLibs.

For example, I don't use direct placement of libraries (because they already exist elsewhere - in my case in docker image with all required prebuilts, SDK, NDK, etc.) but instead of it I just use linking to them to put them in APK. And if such libraries are also needed at build time, cmake can simply uses 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
    .
Mykola Khyliuk
  • 1,234
  • 1
  • 9
  • 16