在Android Studio中使用预构建的共享库
我需要在我的android项目中使用自定义预构建共享库(构建于独立ndk上,作为libdynamic.so)。我在路径src/main中创建了一个文件夹“jniLibs”,然后在“armeabi”“armeabi-v7a”“x86”“x86_64”中创建了4个文件夹。我已将预建的库放入所有这4个文件夹中。在Android Studio中使用预构建的共享库
现在来自我的本地代码,我想调用这个库的一个函数。以下列方式(在的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());
}
我收到以下错误:
Error:error: cannot find -ldynamic
Error:(19) undefined reference to 'rsqrt(float)'
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推动和android壳库。这是使用Android Studio的apk版本造成的问题。我正在使用Android Studio版本2.3.3。任何帮助,高度赞赏。
我能使其工作使用Android.mk而不是cmake。我发布了Android.mk和gradle build的配置和内容,以防万一需要它。
在“app”下创建一个文件夹“jni”。创建另一个自定义文件夹“yourlibs”,并将这个“yourlibs”文件夹中的所有预建库存放到相应的“TARGET_ARCH_ABI”文件夹中。例如,在我的情况:
- JNI/yourlibs/armeabi/libdynamic.so
- JNI/yourlibs/armeabi-V7A/libdynamic.so
- JNI/yourlibs/86/libdynamic.so
- JNI/yourlibs/x86_64的/ libdynamic.so
现在,请按照下列步骤操作:
- 创建一个 “C” F在你要调用在“libdynamic.so”中定义的函数的“jni”文件夹中。添加必要的头文件到您创建的“C”文件中。对我来说, “uselib.c” 和 “header.h”
- 创建一个名为 “Android.mk” 中的 “JNI” 文件夹内
添加以下内容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更新版本(应用程序)文件中使用的 “Android.mk”,而不是cmake的:
Inside “的机器人=> defaultConfig”
ndk{
abiFilters 'armeabi', 'armeabi-v7a', 'x86', 'x86_64'
}
内部“Android”的
externalNativeBuild {
ndkBuild {
path "jni/Android.mk"
}
}
这将使一个名为“使用-LIB”库,它使用“libdynamic.so”,它会包装既APK的lib文件夹中的库。你可以使用apk分析器(Android Studio => Build => Analyze Apk ...)来检查它。要使用 “使用-lib的” 使用JNI调用,如:
static {
System.loadLibrary("use-lib");
}
public native String stringFromJNI();
注:我删除的extern “C” 语句从C代码。
为了加载通过CMake在Android的环境资料库,你将不得不添加以下代码在本地-lib中的CMakeLists.txt:
设置你的库路径
set(LIBS_DIR ${CMAKE_SOURCE_DIR}/../jniLibs)
添加库导入
add_library(DYNAMIC_LIB SHARED IMPORTED)
组库升ocation每个ABI
set_target_properties(DYNAMIC_LIB PROPERTIES IMPORTED_LOCATION ${LIBS_DIR}/${ANDROID_ABI}/lidynamic.so)
链接库导入到目标
target_link_libraries(native-lib DYNAMIC_LIB)
并在本机的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'
}
}
添加SYSROOT lib目录到LDFLAGS使用-L因为如果我正确地记得libdynamic也依赖于libc,libdl,并且至少应该要求libm。
的路径应该是:
$ NDK /平台/ android-(平台版本)/ arch-(架构)/ usr/lib目录
嘿泰坦,谢谢你的回答;但使用你的配置我收到以下错误:“错误:错误:'../../../../../jniLibs/x86/libdynamic.so',需要'../../ .. /../build/intermediates/cmake/debug/obj/x86/libnative-lib.so',缺少并且没有已知规则使其成为“ –
你有没有jni.srcDirs = ['src/main/jniLibs /']在native-lib/build.gradle中?因为这是告诉编译器你的共享库在哪里。 – Titan