简体   繁体   English

在Android Studio中使用预建的共享库

[英]Using Pre-built Shared Library in Android Studio

I need to use a custom prebuilt shared library (built on standalone ndk as libdynamic.so) in my android project. 我需要在我的Android项目中使用自定义的预构建共享库(基于独立ndk构建为libdynamic.so)。 I created a folder "jniLibs" in path src/main and then 4 folders inside that namely "armeabi" "armeabi-v7a" "x86" "x86_64". 我在路径src / main中创建了一个文件夹“ jniLibs”,然后在其中创建了4个文件夹,即“ armeabi”,“ armeabi-v7a”,“ x86”,“ x86_64”。 I have put the prebuilt library inside all these 4 folders. 我已经将预构建的库放在所有这4个文件夹中。

Now from my native code I want to call a function of this library. 现在,从我的本机代码中,我想调用该库的函数。 In the following way (included header in cmakelists.txt): 以以下方式(包含在cmakelists.txt中的标头):

extern "C"
JNIEXPORT jstring JNICALL
Java_demo_co_ru_jnilibtest_MainActivity_stringFromJNI(
    JNIEnv *env,
    jobject /* this */) {

     float inv = rsqrt(3);  //FUNCTION FROM LIBRARY (libdynamic.so)

     std::string hello = "Hello ";
     return env->NewStringUTF(hello.c_str());
}

I get following errors: 我收到以下错误:

  1. Error:error: cannot find -ldynamic

  2. Error:(19) undefined reference to 'rsqrt(float)'

  3. Error:error: linker command failed with exit code 1 (use -v to see invocation)

It seems that shared library is not getting located. 似乎共享库未找到。 I entered following values in CMakeLists.txt 我在CMakeLists.txt中输入了以下值

include_directories( src/main/cpp/include) #include header of libdynamic.so
target_link_libraries(native-lib dynamic)  #dependency of native-lib on libdynamic.so

I added following additional entries inside my gradle build (app): 我在gradle build(app)中添加了以下其他条目:

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

sourceSets {
    main {
        jni.srcDirs = ['src/main/jni', 'src/main/jniLibs/']
    }
}


externalNativeBuild {
    cmake {
        path "CMakeLists.txt"
    }
}

I am able to successfully run the library using android push and android shell. 我能够使用android push和android shell成功运行该库。 It is the apk build using Android Studio that is causing problem. 这是使用Android Studio的apk构建引起的。 I am using Android Studio version 2.3.3. 我正在使用Android Studio版本2.3.3。 Any help is highly appreciated. 非常感谢您的帮助。

In order to load your library with CMake in Android environment you will have to add the following code in native-lib CMakeLists.txt: 为了在Android环境中使用CMake加载您的库,您将必须在本地库CMakeLists.txt中添加以下代码:

Set your libs path 设置你的libs路径

set(LIBS_DIR ${CMAKE_SOURCE_DIR}/../jniLibs)

Add library to import 添加要导入的库

add_library(DYNAMIC_LIB SHARED IMPORTED)

Set library location for each ABI 设置每个ABI的库位置

set_target_properties(DYNAMIC_LIB PROPERTIES IMPORTED_LOCATION ${LIBS_DIR}/${ANDROID_ABI}/lidynamic.so)

Link imported library to target 将导入的库链接到目标

target_link_libraries(native-lib DYNAMIC_LIB)

and in the native-lib build.gradle: 并在本地库build.gradle中:

defaultConfig{
    ...
    externalNativeBuild{
        // Specify the toolchain which was used to cross compile libdynamic.so because Android Studio assumes that you used clang
        arguments '-DANDROID_TOOLCHAIN=gcc'
    }
}

Add the sysroot lib dir to LDFLAGS using -L since if I recall correctly libdynamic also relies on libc, libdl, and should require libm at the very least. 使用-L将sysroot lib dir添加到LDFLAGS,因为如果我没记错的话,libdynamic也依赖libc,libdl,并且至少应该需要libm。

The path should be: 路径应为:

$NDK/platforms/android-(platform-version)/arch-(architecture)/usr/lib $ NDK /平台/ android-(平台版本)/ arch-(体系结构)/ usr / lib

I was able to make it work using Android.mk instead of cmake. 我能够使用Android.mk而不是cmake使其工作。 I am posting configurations and contents of Android.mk and gradle build just in case any one needs it. 我发布Android.mk的配置和内容以及gradle构建,以防万一有人需要它。

Create a folder "jni" under "app". 在“ app”下创建一个文件夹“ jni”。 Create another custom folder "yourlibs" and put all your pre-built libs inside this "yourlibs" folder in respective "TARGET_ARCH_ABI" folder. 创建另一个自定义文件夹“ yourlibs”,并将所有预先构建的库放在相应的“ TARGET_ARCH_ABI”文件夹中的“ yourlibs”文件夹中。 For Example, in my case: 例如,在我的情况下:

  • jni/yourlibs/armeabi/libdynamic.so jni / yourlibs / armeabi / libdynamic.so
  • jni/yourlibs/armeabi-v7a/libdynamic.so jni / yourlibs / armeabi-v7a / libdynamic.so
  • jni/yourlibs/x86/libdynamic.so jni / yourlibs / x86 / libdynamic.so
  • jni/yourlibs/x86_64/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". 在“ jni”文件夹中创建一个“ C”文件,从中可以调用“ libdynamic.so”中定义的函数。 Add neccesary header files to your created "C" file. 将必要的头文件添加到您创建的“ C”文件中。 For me it is "uselib.c" and "header.h" 对我来说,它是“ uselib.c”和“ header.h”
  2. Create a file named "Android.mk" inside the "jni" folder 在“ jni”文件夹中创建一个名为“ Android.mk”的文件

Add following contents in Android.mk 在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: 更新gradle build(app)文件以使用“ Android.mk”而不是cmake:

Inside "android => defaultConfig" 里面的“ android => defaultConfig”

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

Inside "android" 在“ 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. 这将创建一个名为“ use-lib”的库,该库使用“ libdynamic.so”,并将这两个库都打包到apk的lib文件夹中。 You can check this using apk analyser (Android Studio => Build => Analyse Apk ...). 您可以使用apk分析器(Android Studio => Build => Analyze Apk ...)进行检查。 To use "use-lib" use jni call, like: 要使用“ use-lib”,请使用jni调用,例如:

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

public native String stringFromJNI(); 

Note: I removed extern "C" statement from the C code. 注意:我从C代码中删除了extern“ C”语句。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM