在上一篇博客Android 開發之JNI/NDK編程實戰(一)中我們介紹了ndk環境的配置,以及如何在android studio3.0中實現jni編程,其原理其實是使用CMake+gradle的方式實現編譯生成so庫。接下來,我們探討一下如何使用ndk+gradle的方式生成so庫。
步驟:
- 1.ndk環境配置
- 2.新建項目,添加Jni實現類並生成.class文件
- 3.生成.h頭文件
- 4.編寫JniLib.cpp、Android.mk 、Application.mk文件
- 5.配置build.gradle腳本和ndk-build
- 6.編譯生成so庫
1.ndk環境配置
參考 Android 開發之JNI/NDK編程實戰(一):android studio3.0配置ndk環境實現jni編程
2.新建項目,添加Jni實現類並生成.class文件
新建JniLib.java後,聲明調用的so庫名和本地方法
public class JniLib {
static {
System.loadLibrary("jnilib");
}
public native String getJniString();
}
然後拖拽JniLib所在路徑到Terminal終端,執行
javac JniLib.java
生成class文件,如下圖
3.生成.h頭文件
拖拽java路徑到Terminal終端,執行命令如下生成.h文件
javah -jni com.psp.jnitest2.JniLib
4.編寫JniLib.cpp、Android.mk 、Application.mk文件
新建jni目錄,將com_psp_jnitest2_JniLib.h 文件拷貝到jni目錄下,新建JniLib.cpp文件,複製com_psp_jnitest2_JniLib.h裏面的內容別修改如下
extern "C" {
#endif
/*
* Class: com_psp_jnitest2_JniLib
* Method: getJniString
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_psp_jnitest2_JniLib_getJniString
(JNIEnv *env, jobject){
return (*env).NewStringUTF("this is my jni test2");
};
#ifdef __cplusplus
}
#endif
#endif
在jni目錄下編寫Android.mk
// 設置工作目錄,而my-dir則會返回Android.mk文件所在的目錄
LOCAL_PATH := $(call my-dir)
// 清除幾乎所有以LOCAL——PATH開頭的變量(不包括LOCAL_PATH)
include $(CLEAR_VARS)
// 設置模塊的名稱,即編譯出來.so文件名
// 注,要和上述步驟中build.gradle中NDK節點設置的名字相同
LOCAL_MODULE := JniLib
// 指定參與模塊編譯的C/C++源文件名
LOCAL_SRC_FILES =: JniLib.cpp
// 指定生成的靜態庫或者共享庫在運行時依賴的共享庫模塊列表。
include $(BUILD_SHARED_LIBRARY)
在jni目錄下編寫Application.mk
APP_MODULES :=JniLib
//指定需要基於哪些CPU平臺的.so文件
//常見的平臺有armeabi x86 mips,其中移動設備主要是armeabi平臺
//默認情況下,Android平臺會生成所有平臺的.so文件,即同APP_ABI := armeabi x86 mips
//指定CPU平臺類型後,就只會生成該平臺的.so文件,即上述語句all會生成全部平臺的.so文件
APP_ABI := all
5.配置build.gradle腳本和ndk-build
打開app下的build.gradle文件,在 defaultConfig 節點內添加ndk節點和sourceSets,如下
配置ndk-build,打開File-->Settings,配置ndk-build如下,配置好之後點擊ok
6.編譯生成so庫
右鍵點擊JNI類,即右鍵點擊JniLib.java,調用ndk-build生成.so文件
結果如下:
至此,我們的so庫就編譯生成了。
注意:以上步驟中調用ndk-build如果出錯,去掉Android,mk和Application.mk中的註釋即可。