直入正題凌受!
環(huán)境搭建
開(kāi)發(fā)環(huán)境
- MacBook Pro(macOS Sierra10.12.6)
- Android Studio2.3.3
- Gradle 2.3.3
NDK install
1、這里我是采用Android Studio自行安裝的,打開(kāi)AndroidStudio,選擇頂部工具條,Tools->Android->SDK Manager->SDK Tools->NDK 點(diǎn)擊install
2、也可以自行下載ndk包(去AndroidDevTools或者谷歌官方網(wǎng)站下載),下載ndk包后解析到某個(gè)路徑新翎,打開(kāi)Project Structure->設(shè)置 NDK location程帕,同上1設(shè)置NDK路徑
3、NDK環(huán)境變量配置地啰,我們需要使用到ndk-build命令愁拭,打開(kāi)終端 -> 輸入 :vim ~/.bash_profile -> 加入NDK 包的路徑,具體怎么使用vim進(jìn)行編輯請(qǐng)自行百度
4亏吝、保存文件岭埠,關(guān)閉.bash_profile,輸入source .bash_profile或者重新開(kāi)啟一個(gè)terminal 蔚鸥,當(dāng)前配置才會(huì)生效惜论。 命令行輸入ndk-build驗(yàn)證配置是否成功
總之:整個(gè)配置過(guò)程同Android SDK的配置一樣
NDK開(kāi)發(fā)實(shí)戰(zhàn)
1、創(chuàng)建Android項(xiàng)目JniLab
2止喷、查看項(xiàng)目local.properties中加入ndk和sdk的路徑是否正確
ndk.dir=/Users/didi/Library/Android/sdk/ndk-bundle
sdk.dir=/Users/didi/Library/Android/sdk
3馆类、配置項(xiàng)目下的gradle.properties文件,表示我們要使用NDK進(jìn)行開(kāi)發(fā)(缺少這步會(huì)導(dǎo)致后續(xù)無(wú)法通過(guò)alt+enter快捷鍵生成jni文件夾)
android.useDeprecatedNdk=true
4弹谁、在moudle根目錄下的的build.gradle中的defaultConfig標(biāo)簽內(nèi)部里加入如下代碼
ndk{
// 生成的so文件名字乾巧,調(diào)用C程序的代碼中會(huì)用到該名字,需要保持一致
moduleName "algorithm"
// 輸出指定三種平臺(tái)下的so庫(kù)
// 還可以添加 'x86_64', 'mips', 'mips64'
abiFilters "armeabi", "armeabi-v7a", "x86"
}
5、編寫(xiě)jni代碼
通過(guò)System.loadLibrary加載的庫(kù)名要和上述4的moduleName一致预愤,否則會(huì)出現(xiàn)java.lang.UnsatisfiedLinkError問(wèn)題沟于,找不到so庫(kù)
6、執(zhí)行第5步的時(shí)候植康,如上圖所示旷太,對(duì)應(yīng)native方法(getInfo)會(huì)提示找不到對(duì)應(yīng)方法,快捷鍵 alt+enter 會(huì)生成對(duì)應(yīng)jni文件夾销睁,包含algorithm.c文件供璧,此處的native方法還是會(huì)顯示紅色,但是不影響編譯
7榄攀、編譯項(xiàng)目后會(huì)發(fā)現(xiàn)app/build中已經(jīng)生成so文件嗜傅,并且已經(jīng)對(duì)應(yīng)的cpu包就是我們?cè)趃radle中已經(jīng)配置的,并且已經(jīng)調(diào)用成功
PS:編譯時(shí)可能碰到NDK_PROJECT_PATH = null問(wèn)題
暫時(shí)的解決方法:將app module的compileSdkVersion與targetSdkVersion由之前的25改成24(可能也跟最新的NDK版本有關(guān)系)
打包出動(dòng)態(tài)so文件,在其它項(xiàng)目中使用
有時(shí)候我們的需求是這樣的檩赢,我們把一些比較重要的業(yè)務(wù)邏輯封裝到ndk內(nèi)部,對(duì)java層只暴露接口违寞。我們就需要打包出so文件贞瞒,并且可能需要在其他項(xiàng)目中使用,下面將介紹so(符合JNI標(biāo)準(zhǔn))文件的打包趁曼,以及在其他項(xiàng)目中如何正確的調(diào)用
- 編寫(xiě)Android.mk文件军浆,放到j(luò)ni文件夾根目錄,與.c文件同級(jí)
PS:注意中文注釋或者中文空格帶來(lái)的意外麻煩
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := algorithm
LOCAL_SRC_FILES := /Users/sus/example/JniLab/app/src/main/jni/algorithm.c
include $(BUILD_SHARED_LIBRARY)
- 使用ndk-build命令(需要配置NDK環(huán)境變量挡闰,參照上文NDK環(huán)境變量配置)乒融,生成so文件
- 編寫(xiě)Application.mk文件掰盘,放到j(luò)ni文件夾根目錄,與.c文件同級(jí)
APP_PLATFORM := android-14
APP_ABI :=all //打包出所有cpu平臺(tái)so文件
進(jìn)入到main目錄后在terminal中輸入命令赞季,ndk-build工具便會(huì)幫我們打包出所有cpu平臺(tái)so文件
其它項(xiàng)目使用該so文件
- 拷貝so文件到項(xiàng)目的main/jniLibs目錄
- 新建package愧捕,包名與類(lèi)名以及方法名必須與生成so文件的類(lèi)保持一致!
- 使用loadLibrary加載動(dòng)態(tài)庫(kù)申钩,聲明native方法
PS:這里如果你不想新建項(xiàng)目測(cè)試次绘,你可以在main下新建jniLibs文件夾,把libs里的so放到j(luò)niLibs中撒遣,刪除libs文件夾邮偎,然后刪除jni文件夾運(yùn)行也會(huì)起到類(lèi)似在新項(xiàng)目中使用so文件的作用
- 對(duì)于上面說(shuō)的【包名與類(lèi)名以及方法名必須與生成so文件的類(lèi)保持一致!】這個(gè)規(guī)范义黎,讀者可能有疑惑禾进,這樣的約束太死板不夠靈活,我們?cè)谑褂靡恍┌瑂o庫(kù)的第三方SDK的時(shí)候并不記得有這么多限制
- 的確如此廉涕,我們看下第三方SDK是怎么搞的泻云,以Umeng Push SDK為參考來(lái)看一下,我們發(fā)現(xiàn)第三方庫(kù)都會(huì)帶有jar包火的,然后通過(guò)包里面去調(diào)用so文件壶愤,我們只需要使用jar包中暴露的接口方法即可,而上述的規(guī)范可能更適合內(nèi)部人員之間開(kāi)發(fā)和使用so
下載地址:JniLab