承接上一章节分析:【一】Android MediaPlayer整体架构源码分析 -【初始化和创建】
本系列文章分析的安卓源码版本:【Android 10.0 版本】
MediaPlayer设置各种Listener的事件回调处理流程
示例代码如下:
mMediaPlayer.setOnPreparedListener(mPreparedListener);
mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener);
mMediaPlayer.setOnCompletionListener(mCompletionListener);
mMediaPlayer.setOnErrorListener(mErrorListener);
mMediaPlayer.setOnInfoListener(mInfoListener);
mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
mMediaPlayer.setOnSeekCompleteListener(mSeekCompleteListener);
本章主要分析java层和native层事件回调通知机制的实现,native层模块之间回调事件通知实现在后续章节中会再次分析到的。
因此,通过前一章节源码分析可知,他们的回调机制是相同的,都是通过Handler机制实现的。【其实现原理可见我另一章节分析(教你手写android底层Handler消息机制实现框架)】
1、以【setOnPreparedListener】为例:
// [android.media.MediaPlayer.java]
/**
* Register a callback to be invoked when the media source is ready
* for playback.
*
* @param listener the callback that will be run
*/
public void setOnPreparedListener(OnPreparedListener listener)
{
// 只是缓存当前监听事件
mOnPreparedListener = listener;
}
通过源码分析,可知每个setListener接口都只是MediaPlayer缓存该监听接口对象,等到回调事件通知时才返回通知应用层。
2、EventHandler的Handler事件接收处理:
// [android.media.MediaPlayer.java]
@Override
public void handleMessage(Message msg) {
// 由上面的分析可知,【mNativeContext】字段缓存的值是native层MediaPlayer对象指针值
if (mMediaPlayer.mNativeContext == 0) {
Log.w(TAG, "mediaplayer went away with unhandled events");
return;
}
// 所有的底层回调事件都会在此处通过事件类型【不同int值标识】来处理
// 定义了非常多的事件回调类型,但目前只开放了几个listener事件给应用层使用,
// 即可以通过设置setListener的方法监听回调事件,其他事件都是此处内部处理的。
switch(msg.what) {
// prepared状态,即prepare流程执行完成的回调通知事件
case MEDIA_PREPARED:
try {
// 在prepare流程执行完成之后,需要检查是否需要获取底层track集合数据中的
// 类型为【TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE】字幕流track
// 此处不展开分析
// 【通过传递Parcel信息给native层,java层Parcel和native层Parcel转换比较简单,
// 就是java层Parcel创建时缓存了对应native层Parcel对象指针值】
// 可以参考【andr