Chinaunix首页 | 论坛 | 博客
  • 博客访问: 138039
  • 博文数量: 18
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 186
  • 用 户 组: 普通用户
  • 注册时间: 2013-02-04 12:22
文章分类

全部博文(18)

文章存档

2013年(18)

我的朋友

分类: Android平台

2013-03-26 15:46:44

一、分析的文件路径
./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

点击(此处)折叠或打开

  1. public class MediaScanner
  2. {
  3.     static {
  4.     /*加载对应的JNI库*/
  5.         System.loadLibrary("media_jni");
  6.         native_init();//调用native_init()函数
  7.     }
  8.       ........
  9.     private static native final void native_init();//声明一个native函数,native为关键字
  10.     private native final void native_setup();
  11.       ........
  12. }
注:native_init函数位于android.media这个包中,其全路径名称为android.media.MediaScanner.nantive_init,根据规则其对应的JNI层函数名称为:android_media_MediaScanner_native_init。
2、JNI层
android_media_MediaScanner.cpp

点击(此处)折叠或打开

  1. static const char* const kClassMediaScanner =
  2.         "android/media/MediaScanner";
  3.      ........

  4. /*native_init函数的JNI层实现*/
  5. static void android_media_MediaScanner_native_init(JNIEnv *env)
  6. {
  7.     ALOGV("native_init");
  8.     jclass clazz = env->FindClass(kClassMediaScanner);
  9.     if (clazz == NULL) {
  10.         return;
  11.     }
  12.                                                                                                                   
  13.     fields.context = env->GetFieldID(clazz, "mNativeContext", "I");
  14.     if (fields.context == NULL) {
  15.         return;
  16.     }
  17. }
    (1)JNI函数的注册
    Java native函数与JNI函数是一一对应关系,这里采用JNINativeMetho的结构体来记录这种关系。

点击(此处)折叠或打开

  1. typedef struct {
  2.     const char* name;
  3.     const char* signature;
  4.     void* fnPtr;
  5. } JNINativeMethod;

点击(此处)折叠或打开

  1. /*定义一个JNINativeMethod数组*/
  2.     static JNINativeMethod gMethods[] = {
  3.         {
  4.             "processDirectory",
  5.             "(Ljava/lang/String;Landroid/media/MediaScannerClient;)V",
  6.             (void *)android_media_MediaScanner_processDirectory
  7.         },
  8.         .......
  9.         {
  10.             "native_init",//java中native函数的函数名
  11.             "()V",
  12.             /*JNI对应的函数指针*/
  13.             (void *)android_media_MediaScanner_native_init
  14.         },
  15.         {
  16.             "native_setup",
  17.             "()V",
  18.             (void *)android_media_MediaScanner_native_setup
  19.         },
  20.          .......
  21.     };
  22. /*注册JNINativeMethod数组*/
  23. int register_android_media_MediaScanner(JNIEnv *env)
  24. {
  25.     return AndroidRuntime::(env,
  26.                 kClassMediaScanner, gMethods, NELEM(gMethods));
  27. }
接着调用AndroidRuntime中的registerNativeMethods:
AndroidRuntime.cpp

点击(此处)折叠或打开

  1. /*static*/ int AndroidRuntime::registerNativeMethods(JNIEnv* env,
  2.     const char* className, const JNINativeMethod* gMethods, int numMethods)
  3. {
  4.     return jniRegisterNativeMethods(env, className, gMethods, numMethods);
  5. }
JNIHelp.cpp

点击(此处)折叠或打开

  1. extern "C" int jniRegisterNativeMethods(C_JNIEnv* env, const char* className,
  2.     const JNINativeMethod* gMethods, int numMethods)
  3. {
  4.     JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
  5.     
  6.     ALOGV("Registering %s natives", className);

  7.     scoped_local_ref<jclass> c(env, findClass(env, className));
  8.     if (c.get() == NULL) {
  9.         ALOGE("Native registration unable to find class '%s', aborting", className);
  10.         abort();
  11.     }

  12.     if ((*env)->RegisterNatives(e, c.get(), gMethods, numMethods) < 0) {
  13.         ALOGE("RegisterNatives failed for '%s', aborting", className);
  14.         abort();
  15.     }

  16.     return 0;
  17. }
当Java层通过System.loadLibrary加载完JNI动态库后,紧接着会查找一个JNI_OnLoad的函数。如果有就调用它,动态注册的工作在这里完成。
android_media_MediaPlayer.cpp

点击(此处)折叠或打开

  1. jint JNI_OnLoad(JavaVM* vm, void* reserved)
  2. {
  3.     JNIEnv* env = NULL;
  4.     jint result = -1;

  5.     if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
  6.         ALOGE("ERROR: GetEnv failed\n");
  7.         goto bail;
  8.     }
  9.     assert(env != NULL);
  10.      ......
  11.     if (register_android_media_MediaScanner(env) < 0) {
  12.         ALOGE("ERROR: MediaScanner native registration failed\n");
  13.         goto bail;
  14.     }
  15.    .......
  16.     /* success -- return valid version number */
  17.     result = JNI_VERSION_1_4;

  18. bail:
  19.     return result;
  20. }



阅读(5182) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~