AS如何引入第三方so
背景
Android Studio 引入第三方so以及头文件。
情况一:
仅需直接引入SO,并直接调用其暴露的JNI方法
情况二:
无法调用JNI方法,需要引入头文件,在C++层调用其导出方法
情况一解决方案:
- 在src/main/ 目录下新建目录 jniLibs
- 在jniLibs目录下新建目录 armeabi-v7a
- 将so文件以及Needed Library文件copy到armeabi-v7a目录下
- 在build.gradle中,添加以下代码:
android {
...
sourceSets {
main {
jniLibs.srcDirs = ['src/main/jniLibs']
}
}
}
- sync now
备注:要注意包名需要相匹配,同时假设无法运行,可能原因是so文件有做签名校验
情况二解决方案
修改CMakeLists.txt,如下:
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
add_library( # Sets the name of the library.
uUtils
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
${CMAKE_SOURCE_DIR}/src/main/cpp/uDemo.cpp )
# 添加第三方so
add_library(u_jni SHARED IMPORTED)
# 添加第三方so所在位置
set_target_properties(u_jni PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/libu_jni.so)
# 添加头文件
include_directories(uUtils
PRIVATE
${CMAKE_SOURCE_DIR}/src/main/cpp/include)
set_property(TARGET u_jni PROPERTY IMPORTED_NO_SONAME 1)
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
# 链接so
target_link_libraries( # Specifies the target library.
uUtils
u_jni
android
${log-lib} )
修改build.gradle
defaultConfig {
...
externalNativeBuild {
cmake {
cppFlags "-frtti -fexceptions"
}
}
ndk {
abiFilters "armeabi-v7a"
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
sourceSets {
main {
jniLibs.srcDirs += ['libs']
}
}
踩坑记录
引入其中某一个SO文件时,其LD_LIBRARY_PATH即Need library一直为相对路径
可以看到这两个 so 文件有个差别就是 libloki.so 缺少了 SONAME。
CMake 在用 add_library(XXX SHARED IMPORTED) 并通过 IMPORTED_LOCATION 指定 lib full path 导入 lib 时会看这个 lib 有没有 SONAME。如果有的话就把 lib full path 截断并通过 -L/path/to/libXXX -lXXX来链接,如果没有的话就会用全路径 -l/path/to/libXXX.so 来链接。这会导致在链接生成的文件里面 NEEDED 字段一个是 lib name 一个是 lib full path。
解决方案:
set_property(TARGET loki PROPERTY IMPORTED_NO_SONAME 1)