一、分析的文件路径
./frameworks/base/media/java/android/media/MediaScanner.java
./frameworks/base/media/jni/android_media_MediaScanner.cpp
./frameworks/base/media/jni/android_media_MediaPlayer.cpp
./frameworks/base/media/jni/AndroidRuntime.cpp
./libnativehelper/JNIHelp.cpp
二、代码分析
1、java层
MediaScanner.java
-
public class MediaScanner
-
{
-
static {
-
/*加载对应的JNI库*/
-
System.loadLibrary("media_jni");
-
native_init();//调用native_init()函数
-
}
-
........
-
private static native final void native_init();//声明一个native函数,native为关键字
-
private native final void native_setup();
-
........
-
}
注:native_init函数位于android.media这个包中,其全路径名称为android.media.MediaScanner.nantive_init,根据规则其对应的JNI层函数名称为:android_media_MediaScanner_native_init。
2、JNI层
android_media_MediaScanner.cpp
-
static const char* const kClassMediaScanner =
-
"android/media/MediaScanner";
-
........
-
-
/*native_init函数的JNI层实现*/
-
static void android_media_MediaScanner_native_init(JNIEnv *env)
-
{
-
ALOGV("native_init");
-
jclass clazz = env->FindClass(kClassMediaScanner);
-
if (clazz == NULL) {
-
return;
-
}
-
-
fields.context = env->GetFieldID(clazz, "mNativeContext", "I");
-
if (fields.context == NULL) {
-
return;
-
}
-
}
(1)JNI函数的注册
Java native函数与JNI函数是一一对应关系,这里采用JNINativeMetho的结构体来记录这种关系。
-
typedef struct {
-
const char* name;
-
const char* signature;
-
void* fnPtr;
-
} JNINativeMethod;
-
/*定义一个JNINativeMethod数组*/
-
static JNINativeMethod gMethods[] = {
-
{
-
"processDirectory",
-
"(Ljava/lang/String;Landroid/media/MediaScannerClient;)V",
-
(void *)android_media_MediaScanner_processDirectory
-
},
-
.......
-
{
-
"native_init",//java中native函数的函数名
-
"()V",
-
/*JNI对应的函数指针*/
-
(void *)android_media_MediaScanner_native_init
-
},
-
{
-
"native_setup",
-
"()V",
-
(void *)android_media_MediaScanner_native_setup
-
},
-
.......
-
};
-
/*注册JNINativeMethod数组*/
-
int register_android_media_MediaScanner(JNIEnv *env)
-
{
-
return AndroidRuntime::(env,
-
kClassMediaScanner, gMethods, NELEM(gMethods));
-
}
接着调用AndroidRuntime中的
registerNativeMethods:
AndroidRuntime.cpp
-
/*static*/ int AndroidRuntime::registerNativeMethods(JNIEnv* env,
-
const char* className, const JNINativeMethod* gMethods, int numMethods)
-
{
-
return jniRegisterNativeMethods(env, className, gMethods, numMethods);
-
}
JNIHelp.cpp
-
extern "C" int jniRegisterNativeMethods(C_JNIEnv* env, const char* className,
-
const JNINativeMethod* gMethods, int numMethods)
-
{
-
JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
-
-
ALOGV("Registering %s natives", className);
-
-
scoped_local_ref<jclass> c(env, findClass(env, className));
-
if (c.get() == NULL) {
-
ALOGE("Native registration unable to find class '%s', aborting", className);
-
abort();
-
}
-
-
if ((*env)->RegisterNatives(e, c.get(), gMethods, numMethods) < 0) {
-
ALOGE("RegisterNatives failed for '%s', aborting", className);
-
abort();
-
}
-
-
return 0;
-
}
当Java层通过System.loadLibrary加载完JNI动态库后,紧接着会查找一个JNI_OnLoad的函数。如果有就调用它,动态注册的工作在这里完成。
android_media_MediaPlayer.cpp
-
jint JNI_OnLoad(JavaVM* vm, void* reserved)
-
{
-
JNIEnv* env = NULL;
-
jint result = -1;
-
-
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
-
ALOGE("ERROR: GetEnv failed\n");
-
goto bail;
-
}
-
assert(env != NULL);
-
......
-
if (register_android_media_MediaScanner(env) < 0) {
-
ALOGE("ERROR: MediaScanner native registration failed\n");
-
goto bail;
-
}
-
.......
-
/* success -- return valid version number */
-
result = JNI_VERSION_1_4;
-
-
bail:
-
return result;
-
}
阅读(5186) | 评论(0) | 转发(0) |