所有內容為記錄學(xué)習過(guò)程,不是大牛盡情諒解。所有分析都參考深入理解Android 卷一
概括:
在Android平臺上,JNI就是一座將Native世界和Java世界間的天塹變?yōu)橥ㄍ镜臉颉?/span>
JAVA <---> JNI <---> NATIVE
Java世界對應的是MediaScanner 而這個(gè)MediaScanner類(lèi)有一些函數需要由Native層來(lái)實(shí)現
JNI層對應的是libmedia_ni.so庫 media_jni是JNI庫的名字,其中,下劃線(xiàn)前的media是Native層庫的名字。
在Android平臺上基本采用lib模塊名_jni.so的命名方式
Native層對應的是libmedia.so 這個(gè)庫完成實(shí)際功能
MediaScanner 將通過(guò)JNI庫 libMedia_jni.so和Native層
現在看代碼
在frameworks/base/media/java/android/media/MediaScanner.java

加載對應的JNI庫,media_jni是JNI庫名,在實(shí)際加載的時(shí)候拓展成libmedia_jni.so,在windows平臺上擴展為media_jni.dll

Native函數的聲明
現在看一下 native_init();函數
在framewords/base/media/jni/android_media_MediaScanner.cpp

這部分為MediaScanner的JNI代碼
到這里有個(gè)問(wèn)題native_init 怎么就映射成了android_media_MedeaScanner_native_init了
仔細查看 native_init 函數 位于android.media這個(gè)包中MediaScanner.java這個(gè)問(wèn)題中
這么一看思路就有點(diǎn)對了
android.media.MediaScanner.native_init 將這里面的.(點(diǎn))換成下劃線(xiàn)就對應上了。
因為在native語(yǔ)言中,”.”符號點(diǎn)有著(zhù)特殊的含義,所以JNI 層需要把java函數名稱(chēng)(包括包名)中的”.”換成”_” 也就是通過(guò)這種方式native_init 找到了自己的另一半android.;mediaMediaScanner.native_init
可以看出 靜態(tài)方法就是根據函數名來(lái)建立 java函數和JNI函數的關(guān)聯(lián)關(guān)系的,這個(gè)關(guān)聯(lián)關(guān)系由虛擬機完成
下面看一下JNI 中的動(dòng)態(tài)注冊
Java native 函數 和JNI 函數 是一一對應的,其對應該系用一個(gè)結構來(lái)保存。
JNINativeMethod的結構
type struct{
const char* name;//java中的native函數的名稱(chēng),不用攜帶包路徑,例如 native_init
const char* signature;//函數簽名信息,用字符串表示,是參數類(lèi)型和返回值類(lèi)型的組合
void* fnPtr;//JNI層對應函數的函數指針,void*類(lèi)型
} JNINativeMethod;
應該如何使用這個(gè)結構體呢,看一下MediaScanner JNI 層的做法


register_android_media_MediaScanner(JNIEnv *env)函數
調用AndroidRuntime::registerNativeMethods();
完成JNI函數的注冊問(wèn)題
Frameworks/base/core/jni/AndroidRuntime.cpp

Dalvik/libnativehelper/JNIHelp.c

其實(shí)這里面只用兩個(gè)操作就完成了 注冊
第一個(gè)是獲取android/media/MediaScanner 類(lèi)
另一個(gè) 就是將剛才JNINativeMethod 里面注冊的方法和這個(gè)獲取的類(lèi)綁定
為了學(xué)習JNI中的數據類(lèi)型轉換,這里看一下processFile這個(gè)函數


在MediaScanner.java中的定義
Private native void processFile(String path, String mimeType, MediaScannerClient client)
對應的android_media_MediaScanner.cpp中
Static void android_media_MediaScanner_processFile(JNIEnv *env,jobject thiz, jstring path,
Jstring mimetype, jobject client)
Java中的String 對應 JNI 中的jstring
Java中的MediaScannerClient 對應JNI中的jobject
如果都用jobject表示,那么該如何操作呢。
解釋一下JNI層中幾個(gè)函數參數的意義
第一個(gè)JNIEnv 是一個(gè) JAVA環(huán)境,對于這個(gè)變量,暫時(shí)沒(méi)明白,以后分析。
第二個(gè)jobject 由于是非靜態(tài)方法所以傳過(guò)來(lái)的是MediaScanner對象,它表示是安格MediaScnner對象上調用了processFile (如果該函數在java層定義為static寒素那么這個(gè)參數就換位jclass 表示在哪個(gè)class中調用了該靜態(tài)方法 這個(gè)應該很容易理解)
聯(lián)系客服