Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a prebuilt shared Library in Android Studio (cmake)

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.

like image 271
Dario Avatar asked Nov 09 '17 12:11

Dario


Video Answer


2 Answers

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"

like image 85
Ali Maddi Avatar answered Sep 18 '22 06:09

Ali Maddi


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.

like image 33
Nabin Bhandari Avatar answered Sep 21 '22 06:09

Nabin Bhandari