Android的APP開發基本都是使用Java或者跨平台框架進行開發的,對於很多APP來說已經足夠了,但是,對於提供功能給外部使用或者性能要求很高的需求下,如圖像處理等,可能會需要C/C++庫的支持,這就需要借助NDK,另外,NDK在可以起到代碼保護的作用,因為其反編譯查看源碼難度比java更大。
Java代碼是不能直接調用原生的C++代碼的,C++代碼需要借助NDK暴露一個本地接口給JAVA來調用的,原理很多資料都有介紹,這里就不重復了,這里,主要演示一下在Android Studio下如何集成這個編譯環境,這里基於蘋果的Mac OS X系統來搭建,蘋果內核原本就是UNIX的,因此,環境搭建相對Windows方便很多,沒在Windows搭建過,應該也不難。
1. 新建一個測試工程,工程名為:TestJNI:
2. 在app/build.gradle的默認配置塊聲明庫名稱和生成的CPU架構文件,這里模塊名稱是"JimOpencvLibs",那么,對應生成的so庫文件名就是“lib+模塊名.so”了:
ndk{ moduleName "JimOpencvLibs" abiFilters "armeabi", "armeabi-v7a", "x86" }
3. 在gradle.properties文件聲明使用NDK支持,如第18行所示:
4. 在工程屬性設置設置好NDK的路徑,建議使用Android Studio內置最新的NDK版本,否則會遇到編譯不通過問題:
5. 在app的src路徑下新建一個jni文件夾,用戶存放我們的cpp文件:
6. 在需要使用C++代碼的activity類聲明加載的庫和方法,注意:該聲明的方法前有”native“關鍵字:
7. 進入app/src/main/java目錄下執行下圖命令:
將生成一個頭文件“cn_linjk_testjni_MainActivity.h”,內容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class cn_linjk_testjni_MainActivity */ #ifndef _Included_cn_linjk_testjni_MainActivity #define _Included_cn_linjk_testjni_MainActivity #ifdef __cplusplus extern "C" { #endif /* * Class: cn_linjk_testjni_MainActivity * Method: jimOpencvLibsTest * Signature: ()I */ JNIEXPORT jint JNICALL Java_cn_linjk_testjni_MainActivity_jimOpencvLibsTest (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
在第6步里,我們聲明了一個本地方法:public native int jimOpencvLibsTest();,在這個頭文件中,就會按Java_包名_類名_方法名聲明一個jni方法,我們接下來就需要實現這個方法。
8. 實現生產的頭文件的方法:
這里新建了一個測試類。
9. 測試native方法調用:
剛剛在cpp方法是返回10+20的結果,這里看到輸出結果是30,調用沒問題了,后面可以繼續擴展cpp類實現更多功能就可以了。
10. 我們看看生成的so庫的地方:
可以看到,Android Studio已經幫我們生成了mk文件了,很方便,當然我們也可以自己寫。