到此爲止,“土法”編譯和編寫jni的方法已經基本記錄和講解完畢。一定能夠對ndk的本質有了新的認識。而不是那裏面readme和howto文檔中的幾行字,修改android。mk之類云云。。。
當然有了上面的這些底層編譯的探索,加上ndk裏面提供的。h和若干運行時庫,甚至android平臺源代碼裏面編譯出來的靜態二進制包,jni幾乎可以實現任何功能。
還是那句話,“潘多拉”的盒子一旦打開,能否控制得住,就不是google這樣的公司能夠左右的了。
等有時間再來寫寫關於使用google的ndk來編寫和調試jni模塊的方法。。。
其實主要是關於ndk的一些編譯選項的研究和翻譯(其實人家google的文檔已經說的很清楚了)。偶選用的測試環境是slackware 12。0 + android 1。5 r1 for linux + jdk 1。6。0_12,ndk選用的是android 1。5 ndk r1這個版本的(直接解壓就行,免安裝的)。
1、從ndk安裝說起
ndk安裝的時候需要運行一個~/android-ndk-1。5_r1/build/目錄下面的一個叫做host-setup。sh的腳本。大略讀了一下這個腳本,發現這個主要是用來生成out/host/host/config。mk文件的。主要用於指定用戶操作系統的判斷以及支持的編譯器類型(設置makefile中的cc,ar,ld之類的變量)
ndk的目錄介紹。
2、ndk的目錄結構分析
進入android-ndk-1。5_r1目錄,看到如下目錄結構:
GNUmakefile: 標準的makefile格式的文件,用於引用build/core/main。mk的編譯腳本。
README。TXT:基本的說明,沒啥大用,真正有用的文檔都在docs目錄下面。
apps/:存放帶有jni接口的android工程目錄(工程裏面有利用native關鍵字定義的java函數)
build/:存放着幾乎所有的ndk編譯相關的腳本以及必要的靜態鏈接庫。
docs/:存放這ndk的所有“官方”文檔,每一篇文檔對於jni編寫者來說這裏面的任何一點點資料都是無價的。
out/:存放一些中間的臨時文件,例如jni的。c/。cpp文件編譯過程中產生的。o文件等。
sources/:存放jni文件的。c/。cpp的源代碼文件。
3、基本的使用方法
(1)創建一個android工程
進入apps目錄,運行如下命令:
android create project --target 2 --package com。TWM --activity NDKTest --path 。/NDKTest/project
通過命令行創建一個叫做NDKTest的activity,注意這裏的--path需要設置爲。/XXXXX/project這個目錄,這個XXXXX目錄主要是爲了ndk的make區分不同項目和工程使用的。編寫Application。mk文件的時候,一定要把Application。mk寫到這個XXXXX目錄下面。
$NDK/apps/<myapp>/Application。mk
另外,編譯jni庫的時候使用的命令也是如此:
make APP=<your app name>
這裏的<your app name>實際上也是這個XXXXX目錄。
(2)爲工程添加一個jni的java調用接口
進入app/NDKTest/project/src/com/TWM/NdkTest目錄,建立一個新的java文件(例如:NDKJni。java),然後把代碼寫成類似下面這個樣子:
java代碼:
這裏的MyFunc由於是使用native修飾,因此,這個MyFunc函數是一個調用jni的函數。
(3)爲java工程編寫Application。mk文件
該文件主要放在app/NDKTest目錄下,用於告知ndk的編譯腳本,當前的程序需要哪個jni模塊。
看上去應該是這個樣子的:
APP_PROJECT_PATH := $(call my-dir)/project ---> 當前目錄下的project目錄包含了jni模塊的java接口
APP_MODULES := NDKTest --->當前模塊的名字叫做NDKTest
(4)弄清楚java程序的包層次
以當前的這個project爲例,就是上面代碼中的package com。TWM。NdkTest,定義的類名爲NDKJni。因此,根據這個包的層次,可以根據jni文件的函數命名規則定義函數:
JNIEXPORT jint JNICALL Java_com_TWM_NdkTest_NDKJni_MyFunc(JNIEnv * env, jobject thiz, jint a, jint b) ;
當然,手工根據包層次定義jni函數還是很痛苦的,可以藉助於javah工具:
mkdir -p apps/NDKTest/project/jni
cd apps/NDKTest/project/jni
javah -classpath "/bin/classes" com。TWM。NdkTest。NDKJni
然後就會自動生成一個叫做com_TWM_NdkTest_NDKJni。h的文件,裏面的內容基本上跟手工生成的差不多:
java代碼: