JNI概述
JNI,全稱爲Java Native Interface,即Java本地接口,通過使用 Java本地接口書寫程序,可以確保代碼在不同的平臺上方便移植。
使用Android Studio新建一個項目,選擇Native C++
關於module的build.gradle
android {
//省略了其他代碼
defaultConfig {
externalNativeBuild {
cmake {
//值爲""是因爲創建項目選的ToolChain Default
cppFlags ""
}
}
}
externalNativeBuild {
cmake {
//外部構建腳本路徑
path "src/main/cpp/CMakeLists.txt"
version "3.10.2"
}
}
}
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
sample_text.text = stringFromJNI()
}
external fun stringFromJNI(): String
companion object {
init {
System.loadLibrary("native-lib")
}
}
}
我新建的kotlin項目,如果是java項目的話,就不需要使用伴生對象(companion 關鍵字修飾的對象)和external關鍵字。在java中使用static和native關鍵字:
static {
System.loadLibrary("native-lib");
}
public native String stringFromJNI();
native-lib.cpp
#include <jni.h>
#include <string>
extern "C" JNIEXPORT jstring JNICALL
Java_com_phz_myapplication_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
分析:“Java_com_phz_myapplication_MainActivity_stringFromJNI”字段是不是很熟。
com.phz.myapplication是包名,MainActivity是當前活動,stringFromJNI是方法名。還有返回了String,都跟Activity對應上了。所以除了so文件,cpp文件也可以直接加載,然後使用他的方法。
CMakeLists.txt
以cpp目錄下的CMakeLists.txt爲例(去掉了註釋)
cmake_minimum_required(VERSION 3.4.1)
add_library( native-lib SHARED native-lib.cpp )
find_library( log-lib log )
target_link_libraries( native-lib ${log-lib} )
關於cmake命令,可以參考文檔:cmake-commands
add_library(<name> [STATIC | SHARED | MODULE]
[EXCLUDE_FROM_ALL]
[source1] [source2 ...])
target_link_libraries(<target> ... <item>... ...)
整個調用流程
- Gradle調用外部構建腳本CMklist.txt。
- CMake按照腳本中的命令將C++源文件native-lib.cpp編譯成native-lib.so動態庫,並把它編譯到APK中。
- 運行時首先加載native-lib.so,然後調用so中的stringFromJNI方法,最後把這個方法返回的值顯示在TextView上。
關於build之後編譯出的so路徑
app/build/intermediates/cmake
CMakeLists.txt添加多個依賴和單依賴
關於路徑
c語言相關資源一般都是放在cpp文件夾下。記得之前有在module的build.gradle設置cmake的path。(path “src/main/cpp/CMakeLists.txt”)我們先新建一個文件夾haizhuo,添加haizhuo-lib.cpp文件。
之後,我們可以通過修改CMakeLists.txt把haizhuo-lib.cpp加進依賴,有2種方式,可以選擇編譯成一個庫文件還是二個庫文件。
1. 把haizhuo-lib.cpp同native-lib.cpp一起編譯到到native-lib包裏,只需要修改:
add_library(native-lib HARED native-lib.cpp haizhuo/haizhuo-lib.cpp)
2. 編譯成2個庫文件,不僅需要修改CMakeLists.txt,還需要添加System.loadLibrary(String libname)
cmake_minimum_required(VERSION 3.4.1)
add_library(native-lib SHARED native-lib.cpp)
add_library(haizhuo-lib SHARED haizhuo/haizhuo.cpp)
find_library(log-lib log)
target_link_libraries(native-lib ${log-lib} )
target_link_libraries(haizhuo-lib ${log-lib} )
companion object {
init {
System.loadLibrary("native-lib")
System.loadLibrary("haizhuo-lib")
}
}
補充:關於能添加的源文件類型
//關於源文件,下面的都能加進依賴
.c .C .c++ .cc .cpp .cxx .m .M .mm .h .hh .h++ .hm .hpp .hxx .in .txx