本博客内容来自《深入理解android卷一》
android分为三层:java层,JNI层,Native层
这里以MediaScanner为例:
java层:
public class MediaScanner { staic{ System.loadLibrary("media_jni"); native_init();//调用native_init函数 } ... public void scanDirectories(String[] directories,String volumnName){ ...... } //申明一个native函数。native为java的关键字,表示它将由jni层完成 private static native final void native_init(); private native void processFile(String path,String mimeType,MediaScannerClient client); }
JNI层:
代码位置:android_media_MediaScanner.cpp
static void android_media_MediaScanner_native_init(JNIEnv *env) { jclass clazz; clazz = env->FindClass("android/media/MediaScanner");//java层文件代码路径 ... fields.context = env->GetFieldID(clazz,"mNativeContext","I"); ... return; } //这个函数是processsFile的JNI层实现 static void android_media_MediaScanner_processFile(JNIEnv *env,jobject thiz,jstring path,jstring mimetype,jobject client){ MediaScanner *mp = (MediaScanner *)env->GetIntField(thiz,fields.contenxt); ... const char *pathStr = env->GetStringUTFChars(path,NULL); ... if(mimeType){ env->ReleaseStringUTFChars(mimeType,mimeTypeStr); } }
问题:native_init();层如何知道android_media_MediaScanner_native_init的位置
android.media.MediaScanner.native_init换算成android_media_MediaScanner_native_init
答:一共有两种方式注册
1、静态方法
先编写JAVA代码,然后编译生成.class文件
使用javah -o output packagename.classname生成的output.h文件中,就申明了JNI函数
2、动态注册
在libmedia_jni.so实现JNI_OnLoad
jclass clazz = (*env)->FindcClass(env,className);
(*env)->RegisterNatives(env,clazz,gMethods,numMethods);
jint JNI_OnLoad(JavaVm *vm,void * reserved)
{
JNI
}