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

我需要在我的android项目中使用自定义的预建共享库(在独立的ndk上构建为libdynamic.so)。 我在路径src / main中创建了一个文件夹“jniLibs”,然后在其中创建了4个文件夹,即“armeabi”“armeabi-v7a”“x86”“x86_64”。 我已将预构建的库放在所有这4个文件夹中。

现在从我的本机代码我想调用这个库的一个函数。 按以下方式(在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()); } 

我收到以下错误:

  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)

似乎共享库没有找到位置。 我在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 

我在gradle构建(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" } } 

我能够使用android push和android shell成功运行库。 这是使用Android Studio的apk版本导致问题。 我使用的是Android Studio 2.3.3版。 任何帮助都非常感谢。

要在Android环境中使用CMake加载库,您必须在native-lib CMakeLists.txt中添加以下代码:

设置libs路径

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

添加要导入的库

add_library(DYNAMIC_LIB SHARED IMPORTED)

为每个ABI设置库位置

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

将导入的库链接到目标

target_link_libraries(native-lib DYNAMIC_LIB)

并在native-lib 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' } } 

使用-L将sysroot lib目录添加到LDFLAGS,因为如果我没记错,libdynamic也依赖于libc,libdl,至少应该需要libm。

路径应该是:

$ NDK /平台/ android-(平台版本)/ arch-(架构)/ usr / lib目录

我能够使用Android.mk而不是cmake使其工作。 我正在发布Android.mk和gradle构建的配置和内容,以防任何人需要它。

在“app”下创建一个“jni”文件夹。 创建另一个自定义文件夹“yourlibs”,并将所有预先构建的库放在相应“TARGET_ARCH_ABI”文件夹中的“yourlibs”文件夹中。 例如,在我的情况下:

  • JNI / yourlibs / armeabi / libdynamic.so
  • JNI / yourlibs / armeabi-V7A / libdynamic.so
  • JNI / yourlibs / 86 / libdynamic.so
  • JNI / yourlibs / x86_64的/ libdynamic.so

现在请执行以下步骤:

  1. 在“jni”文件夹中创建一个“C”文件,您可以在其中调用“libdynamic.so”中定义的函数。 将必要的头文件添加到您创建的“C”文件中。 对我来说是“uselib.c”和“header.h”
  2. 在“jni”文件夹中创建名为“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) 

更新gradle build(app)文件以使用“Android.mk”而不是cmake:

在“android => defaultConfig”里面

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

里面的“机器人”

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

这将创建一个名为“use-lib”的库,它使用“libdynamic.so”,它将把这两个库打包到apk的lib文件夹中。 你可以使用apk分析器检查这个(Android Studio => Build => Analyze Apk …)。 要使用“use-lib”,请使用jni调用,如:

 static { System.loadLibrary("use-lib"); } public native String stringFromJNI(); 

注意:我从C代码中删除了extern“C”语句。