mOpenSubtitleSources = new Vector();
//通过Binder机制获取到原生的OPS服务
IBinder b = ServiceManager.getService(Context.APP_OPS_SERVICE);
mAppOps = IAppOpsService.Stub.asInterface(b);
//通过之后获取到的服务,就能使用native_setup方法开始创建MediaPlayer了,而且还是软引用,
//接下来就是放在C++层去创建MediaPlayer了
native_setup(new WeakReference(this));
}
MediaPlayer构造函数总结
-
定义Looper
-
初始化一个TimeProvider
-
通过Binder获取原生
ops服务
-
进入c++层创建一个弱引用的MediaPlayer
所以接下来我们就进入C++层,去分析Native层如何创建MediaPlayer的了。
在分析native_setup
之前,请注意 .so文件
一般都是在静态代码块中加载的。在MediaPlayer中有一段静态代码块,用于加载和链接库文件media_jni.so
:
static {
System.loadLibrary(“media_jni”);
native_init();
}
所以我们要去查看 "media_jni"这个c代码,Android Studio是看不到JNI文件的
我们要去Android源码大全这上面去找,代码是通过 loadLibrary(xxx_jni)
加载的,那么我的搜索关键字就是 libxxx_jni
。
然后我们就找到目录/frameworks/base/media/jni下的android_media_MediaPlayer.cpp文件,从它来分析,因为它的第一个函数 android_media_MediaPlayer_init就是从Java静态代码快调过来的nativie_init
:
//android_media_MediaPlayer.cpp
static void
android_media_MediaPlayer_native_init(JNIEnv *env) {
//类的句柄
jclass clazz;
//这里通过Native层调用Java层,获取MediaPlayer对象
clazz = env -> FindClass(“android/media/MediaPlayer”);
if (clazz == NULL) {
//判空
return;
}
//获取成员变量mNativeContext,它是一个long型,实际对应的是一个内存地址
fields.context = env -> GetFieldID(clazz, “mNativeContext”, “J”);
if (fields.context == NULL) {
return;
}
fields.post_event = env -> GetStaticMethodID(clazz, “postEventFromNative”,
“(Ljava/lang/Object;IIILjava/lang/Object;)V”);
if (fields.post_event == NULL) {
return;
}
…
}
init方法总结:
-
被通知init后,从Java层获取一个MediaPlayer
-
从MediaPlayer获取一些变量
-
从MediaPlayer获取
postEventFromNative()
并执行
这个方法顾名思义:Native通知Java层,我初始化好了,你可以开始做一些事情了。
这个时候我们就要去Java层中看 postEventFromNative()
这个方法做什么了。
private static void postEventFromNative(Object mediaplayer_ref,
int what, int arg1, int arg2, Object obj)
{
//得到弱引用的MediaPlayer
final MediaPlayer mp = (MediaPlayer)((WeakReference)mediaplayer_ref).get();
if (mp == null) {
return;
}
…
//如果handler不为空,则发送一条message
if (mp.mEventHandler != null) {
Message m = mp.mEventHandler.obtainMessage(what, arg1, arg2, obj);
mp.mEventHandler.sendMessage(m);
}
}
postEventFromNative总结
总的来说,就是拿到Native层创建好的MediaPlayer,并且向Handler发送一条message,至于后面做了啥之后再讲。
我们之前在create()的时候,创建MediaPlayer之后,会走native_setup方法,我们来看看这个方法做了什么:
//android_media_MediaPlayer.cpp
static void
android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this)
{
ALOGV(“native_setup”);
sp mp = new MediaPlayer();
…
// 给MediaPlayer创建一个Listener,便于我们在Java层设置的 setPrepareListener、setOnCompleteListener能产生回调
sp listener = new JNIMediaPlayerListener(env, thiz, weak_this);
mp->setListener(listener);
// 对于Java层来说,C++中的MediaPlayer是不透明的,也无需关心其对应的逻辑,各司其职就行了
setMediaPlayer(env, thiz, mp);
}
<