基于Android8.1代码
先从源头开始看
frameworks/base/media/java/android/media/MediaPlayer.java
public MediaPlayer() {
super(new AudioAttributes.Builder().build(),
AudioPlaybackConfiguration.PLAYER_TYPE_JAM_MEDIAPLAYER);
//1
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;
}
//2
mTimeProvider = new TimeProvider(this);
//3
mOpenSubtitleSources = new Vector<InputStream>();
//4
/* 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));
//5
baseRegisterPlayer();
}
1 创建EventHandler(重点)
后面jni回调java时会调用到postEventFromNative, postEventFromNative会将消息发给handler处理
2 mTimeProvider
对这个不太了解, 这是MediaPlayer的一个内部类,继承自MediaTimeProvider, 好像是一个用了提供Meida 播放,seek,buffer时间数据的类。
3 mOpenSubtitleSources
字幕源
4 native_setup(重点)
是对 native层MediaPlayer和回调listener的创建和初始化
5 baseRegisterPlayer()
这个函数在MediaPlayer的父类PlayerBase.主要是获取AppOpsService, 即Application Operations Service,是关于系统应用权限管理的,这些API不对第三方应用开放。
这里主干创建流程主要关注1 和 4. 即创建handle和native层的MediaPlayer, 后续native层即可回调java层接口,java层将信息发送给handle处理
frameworks/base/media/jni/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 in an opaque field in the Java object.
setMediaPlayer(env, thiz, mp);
}
native_setup做了几件事情,
1 创建native层播放器实例MediaPlayer()
2 创建了JNIMediaPlayerListener,将java的MediaPlayer实例传递进去
3 将JNIMediaPlayerListener 设置给MediaPlayer()
4 将FFMediaPlayer 设置给Java层的mNativeContext
后面native层的MediaPlayer 就通过JNIMediaPlayerListener 回调java层接口。JNIMediaPlayerListener 能够访问全局变量 fields.post_event, 同时拥有 java的MediaPlayer实例,所以JNIMediaPlayerListener能够回调java层的postEventFromNative,并将MediaPlayer实例传递回去
关于这一部分listener的介绍可以参考
frameworks/av/media/libmedia/mediaplayer.cpp
MediaPlayer::MediaPlayer()
{
ALOGV("constructor");
mListener = NULL; // MediaPlayerListener, JNIMediaPlayerListener的父类,回调java层
mCookie = NULL;
mStreamType = AUDIO_STREAM_MUSIC;
mAudioAttributesParcel = NULL;
mCurrentPosition = -1;
mCurrentSeekMode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC;
mSeekPosition = -1;
mSeekMode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC;
mCurrentState = MEDIA_PLAYER_IDLE; //播放器当前状态 IDLE
mPrepareSync = false;
mPrepareStatus = NO_ERROR;
mLoop = false;
mLeftVolume = mRightVolume = 1.0;
mVideoWidth = mVideoHeight = 0;
mLockThreadId = 0;
mAudioSessionId = (audio_session_t)
AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
AudioSystem::acquireAudioSessionId(mAudioSessionId, -1);
mSendLevel = 0;
mRetransmitEndpointValid = false;
}
在构造函数里将mCurrentState 设置成MEDIA_PLAYER_IDLE