Android Studio快速實現一個JNI示例
前提:Android+Studio/">Android Studio 3.0,預先通過SDK Manager安裝好CMake(生成so庫的編譯相關工具),3.6.4版
- 定義一個Java類,其中定義native方法,並呼叫System.loadLibrary載入so庫
public class TestJni { static { System.loadLibrary("test-jni"); } public static native String getStringFromNativeMethod(); }
測試呼叫的例子:
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // call native method, LogUtils是封裝的Log類 LogUtils.d("print: " + TestJni.getStringFromNativeMethod()); } }
-
通過javah指令生成C/C++標頭檔案.h
sudo javah -jni com.kevin.test.TestJni
生成的標頭檔案名稱:com_kevin_test_TestJni.h,內容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_kevin_test_TestJni */ #ifndef _Included_com_kevin_test_TestJni #define _Included_com_kevin_test_TestJni #ifdef __cplusplus extern "C" { #endif /* * Class:com_kevin_test_TestJni * Method:getStringFromNativeMethod * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_kevin_test_TestJni_getStringFromNativeMethod (JNIEnv *, jclass); #ifdef __cplusplus } #endif #endif
注意,javah前:
a. 需要先make project一次,生成TestJni.class檔案
b. 先cd至命令執行的路徑:app/build/intermediates/classes/debug,否則會找不到TestJni.class
- 複製標頭檔案至原始碼路徑下面,例如:app/src/main/jni,並新建一個cpp檔案,名字:com_kevin_test_TestJni.cpp,完成函式getStringFromNativeMethod的C++定義,如下:
#include "com_kevin_test_TestJni.h" JNIEXPORT jstring JNICALL Java_com_kevin_test_TestJni_getStringFromNativeMethod (JNIEnv *env, jclass thiz) { return (*env).NewStringUTF("this is c++ code"); }
注意:
這裡C/C++都可以,C的source檔案結尾為.c,C++的source檔案結尾為.cpp,但是語法實現時不能有錯,否則編譯時會報錯。這裡選用C++
- Java程式碼,C++程式碼都準備完成後,這時要準備編譯C++的CMakeList.txt,新建即可。作用是CMake工具的配置檔案,必不可少。簡單配置如下:
cmake_minimum_required(VERSION 3.4.1) add_library( # Specifies the name of the library. test-jni # Sets the library as a shared library. SHARED # Provides a relative path to your source file(s). com_kevin_test_TestJni.cpp )
注意:這裡定義了編譯生成的庫檔名字,test-jni,編譯完成後,檔名稱為:libtest-jni.so。
- 更新app下build.gradle檔案,新增Cmake相關資訊
android { ... defaultConfig { ... externalNativeBuild { cmake { abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a' // 定義編譯的ABI型別,每種會編譯生成一個對應的so庫檔案 } } } ... externalNativeBuild { cmake { path 'src/main/jni/CMakeLists.txt' } } }
-
重新編譯新的Project,並安裝至手機,執行。此時列印的日誌:
12-03 18:47:03.636 9016 9016 D kevintest: print: this is c++ code
說明Activity執行時,呼叫native方法getStringFromNativeMethod成功,方法實現在libtest-jni.so庫中。另外,可以通過Build->Anaylze APK,檢視apk中,lib路徑下已打包4個libtest-jni.so庫,分別存放至arm64-v8a等資料夾下,提供不同的ABI支援
最後,附上示例Project結構的截圖:

參考文件: ofollow,noindex">https://developer.android.com/studio/projects/add-native-code#create-cmake-script
作者:kevin song,2018.12.3於南京建鄴區