深入理解Android(5)——从MediaScanner分析Android中的JNI
2015-01-11 12:26
525 查看
前面几篇介绍了Android中的JNI和基本用法,这一篇我们通过分析Android源代码中的JNI实例,来对JNI部分做一个总结。
一、通向两个不同世界的桥梁
在前面我们说过,JNI就像一个桥梁,将Java和Native世界紧密的联系在了一起,在Android平台上如果没有Native层的支持我们的系统寸步难行,甚至Java中的虚拟机也是通过Native实现的。
![](http://img.blog.csdn.net/20150111114115896?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZGF3YW5nYW5iYW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
二、MediaScanner类的简单介绍
MediaScannerr完成android中的多媒体文件的扫描工作。例如,mediascanner扫描系统内存和SD卡文件之后,会将扫描的结果加载在数据库中,在Music这个应用程序中看到的显示在activity 的list列表上歌曲专辑名,流派,歌曲时长等信息,都是扫描后的结果放在数据库中,最后读到的数据库中的信息。
MediaScanner这项功能使用到的三种android的基本组件:
1、MediaScannerService(从Service中派生),完成扫描任务,并将扫描结果放入到媒体数据库中。
2、MediaProvider(ContentProvider派生),针对媒体库进行相关操作请求,一般情况就是写,删,查,更操作。
3、MediaScannerReceiver接收外界的扫描请求。
![](http://img.blog.csdn.net/20150111114952600?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZGF3YW5nYW5iYW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
三、MediaScanner注册分析
打开MediaScnner.java可以看到
Java native函数和JNI函数是一一对应的,所以在JNI中,是通过JNINativeMethoid结构来记录这种关系的。下面就是android_media_MediaScanner.cpp中的动态注册表。
第二个属性是参数和返回类型的签名
第三个属性是Native对应函数名字
AndroidRunTime类提供了一个registerNativeMethods函数来完成注册工作,实现如下:
在实际的应用中只用两个函数就可以完成动态注册工作。
一、通向两个不同世界的桥梁
在前面我们说过,JNI就像一个桥梁,将Java和Native世界紧密的联系在了一起,在Android平台上如果没有Native层的支持我们的系统寸步难行,甚至Java中的虚拟机也是通过Native实现的。
二、MediaScanner类的简单介绍
MediaScannerr完成android中的多媒体文件的扫描工作。例如,mediascanner扫描系统内存和SD卡文件之后,会将扫描的结果加载在数据库中,在Music这个应用程序中看到的显示在activity 的list列表上歌曲专辑名,流派,歌曲时长等信息,都是扫描后的结果放在数据库中,最后读到的数据库中的信息。
MediaScanner这项功能使用到的三种android的基本组件:
1、MediaScannerService(从Service中派生),完成扫描任务,并将扫描结果放入到媒体数据库中。
2、MediaProvider(ContentProvider派生),针对媒体库进行相关操作请求,一般情况就是写,删,查,更操作。
3、MediaScannerReceiver接收外界的扫描请求。
三、MediaScanner注册分析
打开MediaScnner.java可以看到
static { System.loadLibrary("media_jni"); native_init(); }在这里加载了动态链接库,再调用了native_init()方法
private static native final void native_init();打开android_media_MediaScanner.cpp可以看到native_init()的实现
// This function gets a field ID, which in turn causes class initialization. // It is called from a static block in MediaScanner, which won't run until the // first time an instance of this class is used. static void android_media_MediaScanner_native_init(JNIEnv *env) { LOGV("native_init"); jclass clazz = env->FindClass(kClassMediaScanner); if (clazz == NULL) { return; } fields.context = env->GetFieldID(clazz, "mNativeContext", "I"); if (fields.context == NULL) { return; } }上面的这种注册方式是静态注册,其实还有一种动态的注册方式
Java native函数和JNI函数是一一对应的,所以在JNI中,是通过JNINativeMethoid结构来记录这种关系的。下面就是android_media_MediaScanner.cpp中的动态注册表。
static JNINativeMethod gMethods[] = { { "processDirectory", "(Ljava/lang/String;Landroid/media/MediaScannerClient;)V", (void *)android_media_MediaScanner_processDirectory }, { "processFile", "(Ljava/lang/String;Ljava/lang/String;Landroid/media/MediaScannerClient;)V", (void *)android_media_MediaScanner_processFile }, { "setLocale", "(Ljava/lang/String;)V", (void *)android_media_MediaScanner_setLocale }, { "extractAlbumArt", "(Ljava/io/FileDescriptor;)[B", (void *)android_media_MediaScanner_extractAlbumArt }, { "native_init", "()V", (void *)android_media_MediaScanner_native_init }, { "native_setup", "()V", (void *)android_media_MediaScanner_native_setup }, { "native_finalize", "()V", (void *)android_media_MediaScanner_native_finalize }, };JNINativeMethod结构体如下:
type struct{ const char* name; const char* signature; void* fnPtr; }JNINativeMethod;第一个属性是Java中native函数的名字
第二个属性是参数和返回类型的签名
第三个属性是Native对应函数名字
AndroidRunTime类提供了一个registerNativeMethods函数来完成注册工作,实现如下:
/* * Register native methods using JNI. */ /*static*/ int AndroidRuntime::registerNativeMethods(JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods) { return jniRegisterNativeMethods(env, className, gMethods, numMethods); }jniRegisterNativeMethods是Android平台提供的一个帮助函数。
在实际的应用中只用两个函数就可以完成动态注册工作。
jclass clazz = (*env)->FindClass(env, className); (*env)->RegisterNatives(env, clazz, gMethods, numMethods);当Java层通过System.loadLibrary加装玩JNI动态库后,紧接着会查找该库中一个叫JNI_OnLoad的函数。如果有,就调用它,而动态注册工作就是在这里完成的。
jint JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv* env = NULL; jint result = -1; if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { LOGE("ERROR: GetEnv failed\n"); goto bail; } assert(env != NULL); if (register_android_media_MediaPlayer(env) < 0) { LOGE("ERROR: MediaPlayer native registration failed\n"); goto bail; } if (register_android_media_MediaRecorder(env) < 0) { LOGE("ERROR: MediaRecorder native registration failed\n"); goto bail; } if (register_android_media_MediaScanner(env) < 0) { LOGE("ERROR: MediaScanner native registration failed\n"); goto bail; } if (register_android_media_MediaMetadataRetriever(env) < 0) { LOGE("ERROR: MediaMetadataRetriever native registration failed\n"); goto bail; } if (register_android_media_AmrInputStream(env) < 0) { LOGE("ERROR: AmrInputStream native registration failed\n"); goto bail; } if (register_android_media_ResampleInputStream(env) < 0) { LOGE("ERROR: ResampleInputStream native registration failed\n"); goto bail; } if (register_android_media_MediaProfiles(env) < 0) { LOGE("ERROR: MediaProfiles native registration failed"); goto bail; } if (register_android_mtp_MtpDatabase(env) < 0) { LOGE("ERROR: MtpDatabase native registration failed"); goto bail; } if (register_android_mtp_MtpDevice(env) < 0) { LOGE("ERROR: MtpDevice native registration failed"); goto bail; } if (register_android_mtp_MtpServer(env) < 0) { LOGE("ERROR: MtpServer native registration failed"); goto bail; } /* success -- return valid version number */ result = JNI_VERSION_1_4; bail: return result; }
相关文章推荐
- 深入理解Android(5)——从MediaScanner分析Android中的JNI
- 深入理解Android(1)——理解Android中的JNI(上)
- 深入理解Android(4)——理解Android中的JNI(下)
- 【Android开发】深入理解硬盘缓存类DiskLruCache:源码分析
- Cubietruck---14. binder分析_深入理解android第六章笔记
- android --- 深入理解 JNI
- 深入理解Android(1)——理解Android中的JNI(上)
- 深入理解Android(1)——理解Android中的JNI(上)
- Android一步步深入理解View(一):LayoutInflater的使用和原理分析
- 深入理解Android(4)——理解Android中的JNI(下)
- Cubietruck---13.sp与wp分析_深入理解android第五章笔记
- 深入理解Android(2)——理解Android中的JNI(中)
- [深入理解Android卷一全文-第十章]深入理解MediaScanner
- 深入理解Android(02)——深入理解JNI与应用
- Android源码分析-深入理解setContentView方法
- Android - 深入理解 JNI
- 深入理解Android(4)——理解Android中的JNI(下)
- [深入理解Android卷一 全文-第二章]深入理解JNI
- [深入理解Android卷一全文-第十章]深入理解MediaScanner
- 深入理解Android内核——Android启动分析