How to Link a Prebuilt Shared Library to an Android Ndk Project

NDK: How to include Prebuilt Shared Library Regardless of Architecture

This worked...

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := box2D-prebuilt
LOCAL_SRC_FILES := ../Box2D/libs/$(TARGET_ARCH_ABI)/libbox2D.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/..
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := box2DHello
LOCAL_SRC_FILES := \
$(subst $(LOCAL_PATH)/,, \
$(wildcard $(LOCAL_PATH)/*.cpp))
LOCAL_LDLIBS := -lm -llog
LOCAL_SHARED_LIBRARIES := box2D-prebuilt
include $(BUILD_SHARED_LIBRARY)

Using my own prebuilt shared library in an Android NDK project

In the documentation of Android.mk, check the PREBUILT_SHARED_LIBRARY script description. Put the .so file in lib (not libs) directory and write an Android.mk file next to it that looks something like:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := Myaccessories
LOCAL_SRC_FILES := libMyaccessories.so
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../jni/include

include $(PREBUILT_SHARED_LIBRARY)

How to add prebuilt *.so libraries in android studio?

The issue is mainly related to the nature of libraries. Libraries are dynamic in Android and needs to be linked at runtime.

libindy.so depends on stl, openssl, libsodium and libzmq.
You will find libgnustl_shared.so in NDK.
All the other needed prebuilt libraries are also available here.

What you need to do is make sure these libraries are present in the jniLibs folder and load these in order libraries before libindy.

System.loadLibrary("libgnustl_shared");
.
.
System.loadLibrary("indy");

Alternate approach:

There is a subproject in Indy where we are using libindy as dependency and we try to create a one fat dynamic library which has all the dependencies.
Link

If you follow the steps like vcx you dont have to have all the defendant l libraries in jniLibs as they will be already part of final .so file

The command which make one fat dynamic library with all the symbols and dependencies is this (from the link pasted above)

${LIBVCX}/target/${CROSS_COMPILE}/release/libvcx.a \
${TOOLCHAIN_DIR}/sysroot/usr/${NDK_LIB_DIR}/libz.so \
${TOOLCHAIN_DIR}/sysroot/usr/${NDK_LIB_DIR}/libm.a \
${TOOLCHAIN_DIR}/sysroot/usr/${NDK_LIB_DIR}/liblog.so \
${LIBINDY_DIR}/libindy.a \
${TOOLCHAIN_DIR}/${CROSS_COMPILE_DIR}/${NDK_LIB_DIR}/libgnustl_shared.so \
${OPENSSL_DIR}/lib/libssl.a \
${OPENSSL_DIR}/lib/libcrypto.a \
${SODIUM_LIB_DIR}/libsodium.a \
${LIBZMQ_LIB_DIR}/libzmq.a \
${TOOLCHAIN_DIR}/${CROSS_COMPILE_DIR}/${NDK_LIB_DIR}/libgnustl_shared.so -Wl,--no-whole-archive -z muldefs

Using Pre-built Shared Library in Android Studio

I was able to make it work using Android.mk instead of cmake. I am posting configurations and contents of Android.mk and gradle build just in case any one needs it.

Create a folder "jni" under "app". Create another custom folder "yourlibs" and put all your pre-built libs inside this "yourlibs" folder in respective "TARGET_ARCH_ABI" folder. For Example, in my case:

  • jni/yourlibs/armeabi/libdynamic.so
  • jni/yourlibs/armeabi-v7a/libdynamic.so
  • jni/yourlibs/x86/libdynamic.so
  • jni/yourlibs/x86_64/libdynamic.so

Now follow these steps:

  1. Create a "C" file inside the "jni" folder from where you would call the function defined inside the "libdynamic.so". Add neccesary header files to your created "C" file. For me it is "uselib.c" and "header.h"
  2. Create a file named "Android.mk" inside the "jni" folder

Add following contents in Android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := yourlibs/$(TARGET_ARCH_ABI)/libdynamic.so
LOCAL_MODULE := add_prebuilt
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_SRC_FILES := uselib.c
LOCAL_MODULE := use-lib
LOCAL_SHARED_LIBRARIES := add_prebuilt
include $(BUILD_SHARED_LIBRARY)

Update gradle build (app) file to use "Android.mk" instead of cmake:

Inside "android => defaultConfig"

 ndk{
abiFilters 'armeabi', 'armeabi-v7a', 'x86', 'x86_64'
}

Inside "android"

externalNativeBuild {
ndkBuild {
path "jni/Android.mk"
}
}

This will make a library called "use-lib" that uses "libdynamic.so" and it will pack both the libraries inside the lib folder of apk. You can check this using apk analyser (Android Studio => Build => Analyse Apk ...). To use "use-lib" use jni call, like:

static {
System.loadLibrary("use-lib");
}

public native String stringFromJNI();

Note: I removed extern "C" statement from the C code.

Unable to link prebuilt static library with shared library in Android NDK

Your problem is probably because of you mix different STL's (versions)

Most of your "undefined reference" is related to:

std::__1
std::__ndk1

Like:

out/target/product/generic_arm64/obj/STATIC_LIBRARIES/libsecuretest_intermediates/libsecuretest.a(MyUtils.cpp.o):function MyUtils::Int32toHexString(int, int): error: undefined reference to 'std::__ndk1::locale::locale()'

Please try to compile also the "libsecuretest" with the AOSP build (maybe the libc++ versions is different).

NOTE:

I tried to check my AOSP libc++ symbols (PLATFORM_VERSION=6.0.1) and get:

$ nm -DC libc++.so | grep 'locale::locale()'
000682ad T std::__1::locale::locale()
000682ad T std::__1::locale::locale()

Also I get same symbols with libc++ from the phones Pixel2(Android9) S8(Andorid 8.0.0)

adb pull /system/lib/libc++.so

[And check it with the same "nm" command...]

But the symbols of the ndk18 is:

$nm -DC libc++_shared.so | grep 'locale::locale()'
00000000000865b0 T std::__ndk1::locale::locale()
00000000000865b0 T std::__ndk1::locale::locale()

How to add prebuilt *.so library in android studio 2.2

currently need to pack it by the app. it could be something like:

    sourceSets {
main {
// let gradle pack the shared library into apk
jniLibs.srcDirs = ['point/to/your/shared-lib']
}
}

one example is: https://github.com/googlesamples/android-ndk/blob/master/hello-libs/app/build.gradle
If your shared lib [yours is inside project path] is close to your project, put relative path of your shared-lib to your CMakeLists.txt would work.

Some background discussion at the bottom of this bug might help:
https://code.google.com/p/android/issues/detail?id=214664&can=8&q=vulkan&colspec=ID%20Status%20Priority%20Owner%20Summary%20Stars%20Reporter%20Opened



Related Topics



Leave a reply



Submit