由于工作岗位调整,开始接触Media相关部分的代码,起初希望在网络上找一下大神们分析软文学习一下就好,由于Google在新的Android版本上修改了Nuplayer的地位,原本NuPlayer主要在系统中负责流媒体的播放,但现在Android基本已经全面弃用AwesomePlayer,很多网络文章介绍的多为之前的AwesomePlayer,所以最终没能找到需要的东西,只好自己入手分析。本次分析主要侧重于对Android中NuPlayer在播放本地文件时的工作流程的分析,由于本人初次接触Media模块很多基本的概念不全,加之对代码也只看了大约两周左右,所以可能存在诸多错误,若有发现,请及时指正,多谢,闲话不多说,切入正题。
Android中,我们通常使用SDK中的MediaPlayer来播放一个media资源,对于一个Application的开发者而言,可以十分容易的通过几个简单的接口来对此进行操作,之所以能如此完全依靠Google在Framework中的强大支持才得以实现,本文重在分析Framework中的Server端流程,但SDK中的使用流程便是对框架分析的一个很好的切入口,所以首先看一下在App中如何播放一个媒体文件。
Android在Java层中提供了一个MediaPlayer的类来作为播放媒体资源的接口,在使用中我们通常会编写以下的代码:
MediaPlayer mp = new MediaPlayer()
mp.setDataSource("/sdcard/filename.mp3");
mp.prepare();
mp.start();
只需寥寥的几行代码我们就可以在Android播放一个媒体文件,当然MediaPlayer的接口远不止示例中的几个,其他的接口使用上都比较简单,不做过多描述,下面放上一张MediaPlayer的状态图,以供参考,好吧,我承认因为懒,我从度娘上盗了张图。
我们的分析主要从刚才的示例代码开始,来看看我们简单的几个步骤会在内部执行什么样的操作。
1.创建MediaPlayer:
首先来看看MediaPlayer的构造函数:
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这个JNI的函数,之上的代码主要是创建了一个Handler和一下辅助类,其中这个Handler的主要作用是接收mediaserver端发来的一些状态消息,这一点我们在之后遇到了再说。先来说说这个native函数,直接到android_media_MediaPlayer.cpp中来看看这个函数的实现。
static void
android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this)
{
ALOGV("native_setup");
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
sp<JNIMediaPlayerListener> listener = new JNIMediaPlayerListener(env, thiz, weak_this);
mp->setListener(listener);
// Stow our new C++ MediaPlayer