版權聲明:本文爲博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
本文鏈接:https://blog.csdn.net/itlavn/article/details/80164456
別人寫好的動態庫,需要自己寫jni包一層,這樣就可以在java中調用這個庫了。其實還有第二種方法,就是使用jna來調用,這樣不用寫jni,但是今天我們不討論jna的用法。這裏介紹如何在Android Studio中,編寫jni調用他人的.so動態庫。
複製動態庫到項目
他人提供的庫,需要包含頭文件,和.so文件。
先看一下我的項目主要目錄:
把他人提供的so庫放在libs目錄下,如圖所示,我這裏他人提供的 libtts.so 包含 armeabi 和 armeabi-v7a這兩種,我全部放在了libs目錄下。
在libs裏面新建一個header目錄,如圖所示,把so庫的頭文件放在裏面。
修改CmakeList.txt文件
在app目錄下新建CmakeLists.txt文件,其實要是在Android Studio新建項目時勾選了使用c++,那麼這個文件和一些其他配置已經有了,稍微修改就行。
先看一下我的CmakeList.txt文件:
# Sets the minimum version of CMake required to build the native
# library. You should either keep the default value or only pass a
# value of 3.4.0 or lower.
cmake_minimum_required(VERSION 3.4.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 )
#資源文件夾的位置libs
set(distribution_DIR ${CMAKE_SOURCE_DIR}/../../../../libs)
#導入類庫,只是作爲引用,不編譯
add_library( tts
SHARED
IMPORTED )
#引用目標類庫是本地類庫位置在libs/armeabi/xxx.so
set_target_properties( tts
PROPERTIES IMPORTED_LOCATION
../../../../libs/${ANDROID_ABI}/libtts.so )
#添加類庫位置在src/main/cpp/xxx.cpp需要編譯
add_library(native-lib
SHARED
src/main/cpp/native-lib.cpp )
#引入頭文件目錄位置
include_directories(libs/header)
#將預構建庫與你本地庫相關聯
target_link_libraries( # Specifies the target library.
native-lib tts
# Links the target library to the log library
# included in the NDK.
${log-lib} )
在你的CmakeLists.txt中參照我這個寫就行,也可以直接複製然後再根據你的項目來修改。
修改app目錄下的 build.gradle 配置文件
先看下我的build.gradle 相關部分的配置:
...
android {
compileSdkVersion 26
defaultConfig {
applicationId "com.smart.astts"
minSdkVersion 16
targetSdkVersion 26
versionCode 1
versionName "1.0"
externalNativeBuild {
cmake {
cppFlags "-frtti -fexceptions"
}
}
ndk {
abiFilters "armeabi", "armeabi-v7a"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
// 設置so文件路徑
sourceSets {
main {
// let gradle pack the shared library into apk
jniLibs.srcDirs = ['libs']
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}
...
參照這個修改即可。
編寫jni代碼
在目錄app/src/main/ 下新建目錄cpp,在cpp目錄下添加native-lib.cpp文件,其實用Android Studio新建項目時勾選使用c++,這個文件已經自動新建好了。
在native-lib.cpp 裏面就有編寫我們自己的代碼,主要功能是調用so庫頭文件裏面的函數。jni裏面的方法名不用自己手寫,下面簡單示例一下。
我在MainActivity.java中新建一個native方法,這個方法返回native提供的字符串。
public native String stringFromJNI();
1
2
這時候這個方法是紅色的,因爲jni裏面還沒有與之對應的方法。
鼠標指針點到方法名上,鍵盤按 “Alt”+“Enter”鍵,出來快捷菜單,選中 “Create function ….” 按“Enter”鍵確認。現在 在native-lib.cpp文件裏就有這個方法了。我們這個方法是要返回一個字符串,所以在native-lib.cpp稍微修改一下這個方法:
extern "C"
JNIEXPORT jstring JNICALL
Java_com_smart_astts_MainActivity_stringFromJNI(JNIEnv *env, jobject instance) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
加載jni庫和so動態庫
然後在MainActivity中靜態加載我們編寫的jni庫,同時也並加載第三方的so庫:
static {
System.loadLibrary("tts");
System.loadLibrary("native-lib");
}
運行,測試jni是否編譯成功
運行一下,如果app成功調用了我們的native方法 stringFromJNI(),我們之前的配置就算寫對了。
調用第三方so庫的方法
接下來就可以根據第三方庫的頭文件,在java代碼裏寫對應的native方法,然後在jni裏面調用頭文件裏面對應的方法。
————————————————
版權聲明:本文爲CSDN博主「itlavn」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/itlavn/article/details/80164456