Android NDK開(kāi)發(fā),沒(méi)有你想象的那么難
DK:Native Development Kit原生開(kāi)發(fā)工具
NDK能干什么:NDK使得在android中,java可以調(diào)用C函數(shù)庫(kù)。
為什么要用NDK:我們都知道,java是半解釋型語(yǔ)言,很容易被反匯編后拿到源代碼文件,在開(kāi)發(fā)一些重要協(xié)議時(shí),我們?yōu)榱税踩鹨?jiàn),使用C語(yǔ)言來(lái)編寫(xiě)這些重要的部分,來(lái)增大系統(tǒng)的安全性。還有,在一些接近硬件環(huán)境下,相信大家都清楚C與java的優(yōu)劣。順帶提一下:NDK并不能顯著提升應(yīng)用效率。why?我們都覺(jué)得C語(yǔ)言比起java來(lái)說(shuō)效率要高出很多,一方面,隨著jdk的不斷更新,java的效率也隨之提高;另一方面,即便使用C語(yǔ)言編碼提高了應(yīng)用效率,但是在java與C相互調(diào)用時(shí)平白又增大了開(kāi)銷(xiāo)。
對(duì)于這些問(wèn)題,這里就不多說(shuō)了,希望詳細(xì)了解的,請(qǐng)各位自行搜索。
NDK開(kāi)發(fā),第一步,當(dāng)然是搭建環(huán)境
首先,去 http://developer.android.com/tools/sdk/ndk/index.html 下載你對(duì)應(yīng)平臺(tái)的開(kāi)發(fā)工具
接著,我們需要實(shí)現(xiàn)linux環(huán)境 下載cygwin http://www.cygwin.com/ (對(duì)于64位的用戶(hù),可以直接下載我已經(jīng)下載好的,百度的鏈接應(yīng)該比在線(xiàn)安裝快一些,正在上傳到我的網(wǎng)盤(pán),稍后將地址放在回復(fù)里面)
選擇在線(xiàn)下載的朋友,建議選擇下圖的地址,(是國(guó)內(nèi)的)
選擇好下載源以后就是選擇下載目錄了。我們用鼠標(biāo)點(diǎn)開(kāi)組件列表中的“Devel”分支,在該分支下,有很多組件,
我們必須的是:binutils,gcc,gcc-mingw,gdb
選好這四個(gè)目錄了以后,就是漫長(zhǎng)的等待了,可以去吃頓飯差不多了。
下面該配環(huán)境變量了:NDK環(huán)境變量需要將NDK根目錄(其實(shí)就是ndk-builder.cmd文件的目錄)加入系統(tǒng)環(huán)境變量
cygwin環(huán)境變量需要將bin目錄加入系統(tǒng)環(huán)境變量
例如我的路徑是:C:\java\android-ndk-r7b 和 C:\java\cygwin\bin 這兩個(gè)
配置好環(huán)境后就可以開(kāi)始編碼了
1、新建一個(gè)android工程
2、在工程目錄下添加名為 jni 的文件夾(必須)
3、在jni文件夾下新建你的.c文件(我的叫Hello.c)
4、在jni文件夾下新建名字為Android.mk文件
.mk文件中加入
- LOCAL_PATH := $(call my-dir) //當(dāng)前路徑(如果你了解shell語(yǔ)言,應(yīng)該可以很輕松的理解)
- include $(CLEAR_VARS)
- LOCAL_MODULE := Hello //要生成的.so庫(kù)名
- LOCAL_SRC_FILES := Hello.c //你的.c文件名字
- include $(BUILD_SHARED_LIBRARY)
現(xiàn)在可以開(kāi)始寫(xiě)我們的C代碼了,當(dāng)然這里不能再去從main函數(shù)開(kāi)始寫(xiě),而是有固定的命名方式
如圖,我的函數(shù)名為:Java_com_example_testndk_MainActivity_helloWorldFromC (Java_包名_類(lèi)名_函數(shù)名)
呵呵,寫(xiě)C的朋友可能要抱怨了,我什么時(shí)候?qū)戇^(guò)這么長(zhǎng)的函數(shù)名了。沒(méi)辦法,這是jni的規(guī)范,以Java_開(kāi)頭,后跟java應(yīng)用的包名加上類(lèi)名,都是以下劃線(xiàn)分割,最后才是跟我們的C函數(shù)名
至于參數(shù)形式以及返回值類(lèi)型,我們可以去jdk目錄下翻閱jni.h文件(我的jni文件目錄:C:\java\jdk1.7.0_25\include\jni),有很多函數(shù)模板(不同于C++模板)
由于源碼太多大家自己去查看吧,我就不貼圖了
在jni.h文件的第104行這里可以看到我們返回的jstring本質(zhì)上就是一個(gè)結(jié)構(gòu)體指針,從C代碼里面可以看到就是一個(gè)指向字符串的指針,在java里也就是一個(gè)數(shù)組。
好了,C代碼講解完畢,回到我們android工程。
從剛才的C代碼函數(shù)名,大家應(yīng)該就可以知道我的java類(lèi)名了(這是必須的,因?yàn)橐灰粚?duì)應(yīng)嘛)
需要注意的是圖中紅色方框中的靜態(tài)代碼塊
學(xué)過(guò)java大家都知道,一個(gè) 類(lèi)在初始化的時(shí)候最先執(zhí)行的不是構(gòu)造方法而是靜態(tài)代碼塊,沒(méi)錯(cuò)也就是這里之所以把System.loadLibrary()放到靜態(tài)代碼塊的原因。從名字我們就可以猜到了,加載庫(kù)(“Hello”)
還記得我們?cè)贏ndroid.mk中聲明的那個(gè)Hello嗎,就是那里的名字
緊接著,看到第12行代碼,回憶java知識(shí)了,用native修飾的方法,表示java的本地方法,也就是我們的C函數(shù)了。(其實(shí)這樣的函數(shù)在 android SDK)中并不少見(jiàn),比如我們常用到的多媒體類(lèi)MediaPlayer,大家可以去看看源碼,這里我就不發(fā)了,里面有很多native方法,因?yàn)橐{(diào)用音 頻驅(qū)動(dòng)嘛。
至此,NDK工程就結(jié)束了,來(lái)測(cè)試一下吧。首先編譯我們的C代碼。打開(kāi)cmd,切換到工程目錄下(工程目錄?右鍵工程名,properties,如上圖)輸 入ndk-builder(當(dāng)時(shí)的環(huán)境變量設(shè)置成功了嗎?去看看安卓工程的libs文件夾里面是不是多出來(lái)了個(gè)libHello.so文件)
然后我們?cè)龠\(yùn)行我們的安卓工程吧。
最后,我再說(shuō)一點(diǎn)自己的看法吧,首先就是C語(yǔ)言的基礎(chǔ),結(jié)構(gòu)體指針一定要掌握的好,好好看看jni.h文件給出了哪些函數(shù),其中還有支持C與java交互的函數(shù),要想用好NDK,先用好JNI