在使用AndroidNDK開發的時候有個事情是很煩人的,那就是建立本地代碼檔案夾,產生本地代碼檔案和建立本地代碼的編譯檔案。特別是實現本地方法的時候,也是比較煩人的,因為本地方法的名字實在是太長了。它的命名規範是:Java_package-name_class-name_method-name(arguments),稍一不留神就會有拼字錯誤,而導致長時間的調試。由於不勘忍受這樣的折磨,也為了不重複同樣的事情(DRY-Don't Repeat Yourself),於是就寫了一個Java程式來做這件事。
這個小工具可以逐個檢查Java檔案,並建立含有本地方法檔案,也即本地代碼檔案,產生Android.mk編譯檔案並更新Java檔案,添加System.loadLibrary。
具體的原則是這樣:
•每個含有本地代碼的Java檔案,產生一個本地檔案,其內含有該檔案中的所有本地方法
•所產生的本地方法是符合標準的JNI,具體的形式是:
複製代碼 代碼如下:return-type Java_package-name_class-name_method-name(arguments){
}
也就是說,所需要做的只是實現這個方法。
•預設本地代碼共用庫的名字是Android項目的名字
有了這個小工具,就可以只在Java中聲明本地方法,運行下這個工具,然後實現本地方法,再編譯就可以了。
可以從<這裡下載>這個小工具。解壓後有三個檔案一個是Java源碼,一個是Jar包(genjni.jar),一個是Shell指令碼(genjni.sh)。放上源碼的原因是,如果有興趣的朋友可以進行改進,但是改進後請
發我一份。下載後,最好修改下Shell指令碼,把Jar檔案的路徑改成具體的存放路徑,否則會報出找不到Jar檔案的錯誤。最後把genjni.sh放到~/bin下面,為了使用時方便。使用的時候要在Android項目的根目錄下面運行genjni.sh就可以了。
下面以一個執行個體方式示範下這個小工具的使用方法:
建立一個項目叫HelloJni,並建立一個HelloJniActivity,在其內聲明一個本地方法getStringFromJni();並用有一個TextView用來顯示getStringFromJni()返回的資訊。另一個本地方法getStatusFromJni(int)是為了顯示用的,沒有使用。這是Java代碼:複製代碼 代碼如下:package com.hilton.hellojni;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class HelloJniActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView text = (TextView) findViewById(R.id.text);
text.setText(getStringFromJni());
}
private native String getStringFromJni();
private native int getStatusFromJni(int type);
}
寫好Java代碼後,從終端進入到項目的根目錄下 複製代碼 代碼如下:$cd HelloJni
$ls
AndroidManifest.xml assets bin default.properties gen proguard.cfg res src
$genjni.sh
appplication HelloJni
package name: com.hilton.hellojni
class name: HelloJniActivity
$ls
AndroidManifest.xml assets bin default.properties gen jni proguard.cfg res src
$ls jni
Android.mk HelloJniActivity.c
開啟查看Android.mk和HelloJniActivity.c 複製代碼 代碼如下:LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := HelloJni
LOCAL_SRC_FILES := HelloJniActivity.c
include $(BUILD_SHARED_LIBRARY)
複製代碼 代碼如下:#include <jni.h>
jstring Java_com_hilton_hellojni_HelloJniActivity_getStringFromJni(JNIEnv* env, jobject thiz) {
}
jint Java_com_hilton_hellojni_HelloJniActivity_getStatusFromJni(JNIEnv* env, jobject thiz, jint type) {
}
再查看HelloJniActivity.java也被更新了,裡面多了載入共用庫的語句: 複製代碼 代碼如下:package com.hilton.hellojni;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class HelloJniActivity extends Activity {
static {
System.loadLibrary("HelloJni");
}
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView text = (TextView) findViewById(R.id.text);
text.setText(getStringFromJni());
}
private native String getStringFromJni();
private native int getStatusFromJni(int type);
}
剩下的工作就是實現本地方法了。
當然這個工具還是有很多問題,歡迎各位反饋,或給出改進意見。
另外,這個工具是用Java寫的,更好的選擇應該是用指令碼來寫,如Perl或Python。還有就是,如果能把這個工具整合到ADT中,或是創造一個完全用於NDK開發的整合工具ANDT,能夠像產生R.java那樣的自動產生本地檔案。比如做一個ANDT工具,整合到Eclipse中,能夠自動當Java中有本地方法聲明後就自動產生本地檔案和編譯檔案。這將是多麼美好的事情啊,將對NDK的開發有重大的協助。我想,Google應該會做一專門用於NDK開發的Eclipse外掛程式,或是在ADT中加入對NDK的支援,因為NDK開放的介面越來越多,使用NDK開發人員也將越來越多,基於NDK開發的應用也將越來越多(2.3及以後的版本,完全可以只用NDK開發出一個Apk,也就是說用純C/C++來開發應用)。希望這一天早些到來。