Mediaplayer的构造函数里面定义了一个Looper,将该Looper初始化为当前线程使用的Looper,如果为空则初始化为主线程的Looper,再使用该Looper作为参数初始化EventHandler对象。mAppOps保存了AppOpsService的代理对象,AppOpsService功能是检测某些应用是否具有某些权限。
public MediaPlayer() {
Looper looper;
if ((looper = Looper.myLooper()) != null) {
mEventHandler = new EventHandler(this, looper);
} else if ((looper = Looper.getMainLooper()) != null) {
mEventHandler = new EventHandler(this, looper);
} else {
mEventHandler = null;
}
mTimeProvider = new TimeProvider(this);
mOpenSubtitleSources = new Vector<InputStream>();
IBinder b = ServiceManager.getService(Context.APP_OPS_SERVICE);
mAppOps = IAppOpsService.Stub.asInterface(b);
/* Native setup requires a weak reference to our object.
* It's easier to create it here than in C++.
*/
native_setup(new WeakReference<MediaPlayer>(this));
}
接下来调用native_setup的native方法进入native层。 Mediaplayer.java的静态代码块中加载了libmedia_jni.so库,这个操作回去调用JNI层的JNI_OnLoad函数。 JNI_Onload函数作用在与确认JNI的版本1.4,在JNI层注册个种组件。JNI_onload同样也注册了MediaPlayer。
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_MediaPlayer(env) < 0) {
ALOGE("ERROR: MediaPlayer native registration failed\n");
goto bail;
}
...
以native_int和native_setup为例说明对应关系: 1.无参数(),返回值为Void(V)的Java层函数native_init在JNI层对应的函数名为android_media_MediaPlayer_native_init。 2.接收一个Object参数,返回值为Void(V)的Java层函数native_setup在JNI层对应的函数名为android_media_MediaPlayer_native_setup。
static JNINativeMethod gMethods[] = {
...
{"native_init", "()V", (void *)android_media_MediaPlayer_native_init},
{"native_setup", "(Ljava/lang/Object;)V", (void *)android_media_MediaPlayer_native_setup},
...
Java层静态代码块使用了native_init,该函数的作用在JNI层将Java层的信息保存在field_t结构体变量中。JNIEnv是一个与线程相关的变量,不同线程的JNIEnv相互独立。由于是获取类的FieldID和MethodID,android_media_MediaPlayer_native_init调用FindClass获得Java层MediaPlaye