android jni的編寫, 控制led燈
jni, java native interface, java的本地介面,如果java程式碼想去呼叫native方法(實際就是c/c++函式),就需要用jni技術,在傳統的java中jni技術就已經存在,但是由於傳統的java程式碼中,不太去寫架構或者平臺相關的程式碼,所以以前jni不是太惹人注意,直到android出現後,android本身是一個linux作業系統, linux中的應用程式設計中就使用c/c++程式碼去呼叫驅動,假如android的應用apk想去呼叫底層的裝置驅動,那麼就必須要去呼叫c/c++程式碼,所以此時jni就顯得很重要,它起著承上啟下的作用.
jni的寫法有好幾種,在這裡先介紹在android原始碼包+linux環境下的jni程式設計方式,隨後會介紹ndk中的jni的程式設計方式
程式設計之前首先需要給大家介紹一個大體的框架,我們需要在apk中去點一個led燈,此時就像做飯一樣,介紹幾個主料:
1, apk,實現button點燈
2, jni程式碼,呼叫linux的系統呼叫,去控制驅動
3, 驅動,完成控制led硬體
首先介紹apk中使用jni中的幾個介面
介面一: 呼叫動態庫
static{
System.loadLibrary("led_jni"); // /system/lib/libled_jni.so
}
介面二: 宣告本地方法
public native int OpenDev();
public native int DevOn();
public native int DevOff();
public native int CloseDev();
介面三: 直接呼叫本地方方法
OpenDev();
apk程式碼的內容如下,非常簡單
jni程式碼的編寫原理: java中呼叫c程式碼的基本原理是通過檢視一個對映表來完成的,比如java中呼叫OpenDev方法時,實際是有一個c/c++函式與它一一對應,所以需要一個對映表,並且將其註冊給dvm,當dvm解析java中的native方法是,會去檢視這個對映表,並執行對應的c/c++函式,同時jni程式碼所在的檔案是需要編譯成動態庫,
jni程式碼可以寫成c檔案或者是cpp檔案,但是建議大家寫成cpp檔案,在此,以下程式碼是寫成一個檔案led_jni.cpp
1, 動態庫中的介面:
a, 獲取dvm的環境變數物件,並測試jni的版本(1.4)
vm->GetEnv((void **)&env, JNI_VERSION_1_4)該方法是dvm給我們提供的方法,用於獲取環境變數物件JNIEnv* env,同時會檢測jni的版本是否是1.4, 該方法正常返回JNI_OK
myRegisterNatives(env);該法是自己去實現的,引數就是通過vm->GetENv方法獲取的
b, myRegisterNatives(env)的實現,主要是為了完成對映表的註冊,會呼叫env->RegisterNatives()方法
env->RegisterNatives(jclass clazz, const JNINativeMethod* methods,jint nMethods)
第一個引數: 將java中native修飾的方法所在的類轉換成jni的class型別(jclass)
jclass mycls = env->FindClass("com/hq/JniLedTestActivity");
env->FindClass中的引數是java中的native方法所在包和類的路徑,這個是必須要注意的,路徑是用Linux常用的路徑表示方式,而不是用windows,也不是用java中的點分方式,同時路徑必須要指定正確,否則會出錯
第二個引數: jni的對映表:
第三個引數: 對映表表的成員個數sizeof(myMethods)/sizeof(myMethods[0])
返回: JNI_OnLoad正常 返回JNI_VERSION_1_4
錯誤返回一個負數
c,接下來就是介紹對映表的構造了:
程式碼的片段介紹完了,貼出完整程式碼
d,程式碼寫好了,Android.mk是為了編譯我們寫的程式碼,程式碼最終會編譯成動態庫:
3,接下來就是驅動部分了,對於不同平臺,led的驅動的寫法是不一樣的,但是基本的寫法就是按照字元裝置的方式去寫,這個算是一個字元裝置驅動的簡單模板,可以參考一下看看