10.3.2 JNI层分析
最后更新于:2022-04-02 05:54:14
现在分析MS的JNI层。在Java层中,有三个函数涉及JNI层,它们是:
- native_init,这个函数由MediaScanner类的static块调用。
- native_setup,这个函数由MediaScanner的构造函数调用。
- processDirectory,这个函数由MS扫描文件夹时调用。
分别来分析它们。
1. native_init函数的分析
下面是native_init对应的JNI函数,其代码如下所示:
**android_media_MediaScanner.cpp**
~~~
static void
android_media_MediaScanner_native_init(JNIEnv*env)
{
jclass clazz;
clazz =env->FindClass("android/media/MediaScanner");
//取得Java中MS类的mNativeContext信息。待会创建Native对象的指针会保存
//到JavaMS对象的mNativeContext变量中。
fields.context = env->GetFieldID(clazz,"mNativeContext", "I");
......
}
~~~
native_init函数没什么新意,这种把Native对象的指针保存到Java对象中的做法,已经屡见不鲜。下面看第二个函数native_setup。
2. native_setup函数的分析
native_setup对应的JNI函数如下所示:
**android_media_MediaScanner.cpp**
~~~
android_media_MediaScanner_native_setup(JNIEnv*env, jobject thiz)
{
//创建Native层的MediaScanner对象
MediaScanner*mp = createMediaScanner();
......
//把mp的指针保存到Java MS对象的mNativeContext中去
env->SetIntField(thiz,fields.context, (int)mp);
}
//下面的createMediaScanner这个函数将创建一个Native的MS对象
static MediaScanner *createMediaScanner() {
#if BUILD_WITH_FULL_STAGEFRIGHT
charvalue[PROPERTY_VALUE_MAX];
if(property_get("media.stagefright.enable-scan", value, NULL)
&& (!strcmp(value, "1") || !strcasecmp(value,"true"))) {
return new StagefrightMediaScanner; //使用Stagefright的MS
}
#endif
#ifndef NO_OPENCORE
returnnew PVMediaScanner(); //使用Opencore的MS,我们会分析这个
#endif
returnNULL;
}
~~~
native_setup函数将创建一个Native层的MS对象,不过可惜的是,它使用的还是Opencore提供的PVMediaScanner,所以后面还不可避免地会和Opencore“正面交锋”。
4. processDirectory函数的分析
看processDirectories函数,它对应的JNI函数代码如下所示:
**android_media_MediaScanner.cpp**
~~~
android_media_MediaScanner_processDirectory(JNIEnv*env, jobject thiz,
jstring path, jstring extensions, jobject client)
{
/*
注意上面传入的参数,path为目标文件夹的路径,extensions为MS支持的媒体文件后缀名集合,
client为Java中的MediaScannerClient对象。
*/
MediaScanner *mp = (MediaScanner*)env->GetIntField(thiz, fields.context);
constchar *pathStr = env->GetStringUTFChars(path, NULL);
constchar *extensionsStr = env->GetStringUTFChars(extensions, NULL);
......
//构造一个Native层的MyMediaScannerClient,并使用Java那个Client对象做参数。
//这个Native层的Client简称为MyMSC。
MyMediaScannerClient myClient(env, client);
//调用Native的MS扫描文件夹,并且把Native的MyMSC传进去。
mp->processDirectory(pathStr,extensionsStr, myClient,
ExceptionCheck, env);
......
env->ReleaseStringUTFChars(path, pathStr);
env->ReleaseStringUTFChars(extensions,extensionsStr);
......
}
~~~
processDirectory函数本身倒不难,但又冒出了几个我们之前没有接触过的类型,下面先来认识一下它们。
5. 到底有多少种对象?
图10-1展示了MediaScanner所涉及的相关类和它们之间的关系:
:-: ![](http://img.blog.csdn.net/20150802165330508?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
图10-1 MS相关类示意图
为了便于理解,便将Java和Native层的对象都画于图中。从上图可知:
- Java MS对象通过mNativeContext指向Native的MS对象。
- Native的MyMSC对象通过mClient保存Java层的MyMSC对象。
- Native的MS对象调用processDirectory函数的时候会使用Native的MyMSC对象。
- 另外,图中Native MS类的processFile是一个虚函数,需要派生类来实现。
其中比较费解的是MyMSC对象。它们有什么用呢?这个问题真是一言难尽。下面通过processDirectory来探寻其中原因,这回得进入PVMediaScanner的领地了。
';