1、MediaPlayer.java
位于/frameworks/base/media/java/android/media目录,主要是对底层media player的封装,主要的方法如seek、pause、play等也都有对应的jni方法。在MediaPlayer类加载时,调用了native_init()方法。该方法主要是jni层的初始化,将jni层的一些变量和java层的一些方法、变量对应起来。在创建MediaPlayer对象时,调用了native_setup()方法。该方法将java层对象和jni层的对象一一对应起来,并绑定jni层的事件回调对象。
2、com_android_MediaPlayer.cpp
位于/frameworks/base/media/jni目录。起到一个承上启下的作用,相当于java层MediaPlayer和native层MediaPlayer之间的桥梁。有几个重要的jni方法和结构体:
// jni层的初始化
android_media_MediaPlayer_native_init(JNIEnv *env)
{
jclass clazz;
clazz = env->FindClass("android/media/MediaPlayer"); // 获取java MediaPlayer类对象
if (clazz == NULL) {
return;
}
// 获取java MediaPlayer的字段指针,用于保存native MediaPlayer的对象指针。通过该指针,
// 所有的java MediaPlayer对象的native方法,都调用到了native MediaPlayer对象的对应方法
fields.context = env->GetFieldID(clazz, "mNativeContext", "I");
if (fields.context == NULL) {
return;
}
// java MediaPlayer的事件回调方法
fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative",
"(Ljava/lang/Object;IIILjava/lang/Object;)V");
if (fields.post_event == NULL) {
return;
}
// 和mNativeContext类似,将native SurfaceTexture对象指针保存在java对象的一个字段中
fields.surface_texture = env->GetFieldID(clazz, "mNativeSurfaceTexture", "I");
if (fields.surface_texture == NULL) {
return;
}
}
// java层native_setup(weak reference)的实现,thiz是java层MediaPlayer,weak_this则是java层MediaPlayer的weak reference。
static void
android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this)
{
ALOGV("native_setup");
// 创建native media player,即BnMediaPlayer对象。MediaPlayer继承与BnMediaPlayer
sp<MediaPlayer> mp = new MediaPlayer();
if (mp == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
return;
}
// create new listener and give it to MediaPlayer
// 使用java层MediaPlayer对象和其弱引用,创建一个事件回调listener对象
sp<JNIMediaPlayerListener> listener = new JNIMediaPlayerListener(env, thiz, weak_this);
mp->setListener(listener); // 给MediaPlayer设置MediaPlayerListener事件回调
// Stow our new C++ MediaPlayer in an opaque field in the Java object.
// 将native MediaPlayer对象指针存入java MediaPlayer的一个字段中
setMediaPlayer(env, thiz, mp);
}
// thiz参数是一个java层MediaPlayer对象,而weak_thiz参数则是这个java对象的weak reference
JNIMediaPlayerListener::JNIMediaPlayerListener(JNIEnv* env, jobject thiz, jobject weak_thiz)
{
// Hold onto the MediaPlayer class for use in calling the static method
// that posts events to the application thread.
jclass clazz = env->GetObjectClass(thiz); // 获取java MediaPlayer的类对象
if (clazz == NULL) {
ALOGE("Can't find android/media/MediaPlayer");
jniThrowException(env, "java/lang/Exception", NULL);
return;
}
mClass = (jclass)env->NewGlobalRef(clazz); // 保存java MediaPlayer的类对象
// We use a weak reference so the MediaPlayer object can be garbage collected.
// The reference is only used as a proxy for callbacks.
mObject = env->NewGlobalRef(weak_thiz); // 保存java MediaPlayer的弱引用
}
JNIMediaPlayerListener::~JNIMediaPlayerListener()
{
// remove global references
JNIEnv *env = AndroidRuntime::getJNIEnv();
env->DeleteGlobalRef(mObject);
env->DeleteGlobalRef(mClass);
}
// native层事件通知到java层
void JNIMediaPlayerListener::notify(int msg, int ext1, int ext2, const Parcel *obj)
{
JNIEnv *env = AndroidRuntime::getJNIEnv();
if (obj && obj->dataSize() > 0) {
jobject jParcel = createJavaParcelObject(env);
if (jParcel != NULL) {
Parcel* nativeParcel = parcelForJavaObject(env, jParcel);
nativeParcel->setData(obj->data(), obj->dataSize());
env->CallStaticVoidMethod(mClass, fields.post_event, mObject,
msg, ext1, ext2, jParcel);
}
} else {
env->CallStaticVoidMethod(mClass, fields.post_event, mObject,
msg, ext1, ext2, NULL);
}
if (env->ExceptionCheck()) {
ALOGW("An exception occurred while notifying an event.");
LOGW_EX(env);
env->ExceptionClear();
}
}
static sp<MediaPlayer> getMediaPlayer(JNIEnv* env, jobject thiz)
{
Mutex::Autolock l(sLock);
// 从java MediaPlayer对象的字段中,获取native MediaPlayer的对象指针
MediaPlayer* const p = (MediaPlayer*)env->GetIntField(thiz, fields.context);
return sp<MediaPlayer>(p);
}
static sp<MediaPlayer> setMediaPlayer(JNIEnv* env, jobject thiz, const sp<MediaPlayer>& player)
{
Mutex::Autolock l(sLock);
sp<MediaPlayer> old = (MediaPlayer*)env->GetIntField(thiz, fields.context);

本文详细解析了Android系统的MediaPlayer架构,从Java层到JNI层再到C++层,包括MediaPlayer.java、com_android_MediaPlayer.cpp、mediaplayer.h/.cpp等文件的分析。深入介绍了MediaPlayer的初始化过程、事件回调机制及不同播放器类型的创建流程。

878

被折叠的 条评论
为什么被折叠?



