MediaPlayer可以通过两种方法进行创建。
方法一:通过new一个MediaPlayer对象的方法进行创建,MediaPlayer的构造函数如下:
方法二:通过MediaPlayer的create方法进行创建。
通过new一个MediaPlayer对象的方法进行创建
MediaPlayer的构造函数如下:
//frameworks/base/media/java/android/media/MediaPlayer.java
public class MediaPlayer extends PlayerBase implements SubtitleController.Listener, VolumeAutomation, AudioRouting
{
public MediaPlayer() {
this(AudioSystem.AUDIO_SESSION_ALLOCATE);
}
}
调用重载方法:
//frameworks/base/media/java/android/media/MediaPlayer.java
public class MediaPlayer extends PlayerBase implements SubtitleController.Listener, VolumeAutomation, AudioRouting
{
private MediaPlayer(int sessionId) {
super(new AudioAttributes.Builder().build(),
AudioPlaybackConfiguration.PLAYER_TYPE_JAM_MEDIAPLAYER);
Looper looper;
if ((looper = Looper.myLooper()) != null) {
mEventHandler = new EventHandler(this, looper); //创建EventHandler对象,用于处理消息
} else if ((looper = Looper.getMainLooper()) != null) {
mEventHandler = new EventHandler(this, looper); //创建EventHandler对象,用于处理消息
} else {
mEventHandler = null;
}
mTimeProvider = new TimeProvider(this);
mOpenSubtitleSources = new Vector<InputStream>();
AttributionSource attributionSource = AttributionSource.myAttributionSource();
// set the package name to empty if it was null
if (attributionSource.getPackageName() == null) {
attributionSource = attributionSource.withPackageName("");
}
/* Native setup requires a weak reference to our object.
* It's easier to create it here than in C++.
*/
try (ScopedParcelState attributionSourceState = attributionSource.asScopedParcelState()) {
native_setup(new WeakReference<MediaPlayer>(this), attributionSourceState.getParcel()); //调用了native_setup()函数,并传入了一个MediaPlayer类型的弱引用实例
}
baseRegisterPlayer(sessionId);
}
}
构造函数中主要处理如下:
1、创建EventHandler对象
EventHandler是MediaPlayer的一个内部类,它专门处理来自Native层的事件,这些事件一般都表明了MediaPlayer现在转移到了某个状态,我们可以在该状态处理什么回调操作。EventHandler的功能较为单一,就是根据底层上抛的事件,进行对应的回调或事件处理。
2、调用了native_setup()方法,并传入了一个MediaPlayer类型的弱引用实例。
3、调用baseRegisterPlayer方法,也就是父类PlayerBase的baseRegisterPlayer方法,注册播放器。
EventHandler处理比较简单,我们在其它流程中分析,下面我们继续分析native_setup方法:
native_setup
调用native_setup会通过jni调用android_media_MediaPlayer的android_media_MediaPlayer_native_setup方法:
//frameworks/base/core/jni/android_media_MediaPlayer.cpp
static void
android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this, jobject jAttributionSource)
{
ALOGV("native_setup");
Parcel* parcel = parcelForJavaObject(env, jAttributionSource);
android::content::AttributionSourceState attributionSource;
attributionSource.readFromParcel(parcel);
sp<MediaPlayer> mp = sp<MediaPlayer>::make(attributionSource); //创建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); //创建JNIMediaPlayerListener对象
mp->setListener(listener); //在Native MediaPlayer实例中保存这个JNIMediaPlayerListener监听