上一篇:https://www.jianshu.com/p/5de2ee571728
下一篇:
https://www.jianshu.com/p/1840eb899ef4
BaseVideoView主要事件
BaseVideoView主要事件分三块:
1、setOnPlayerEventListener
2、setOnErrorEventListener
3、setOnReceiverEventListener
public BaseVideoView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs, defStyleAttr);
}
private void init(Context context, AttributeSet attrs, int defStyleAttr) {
mPlayer = createPlayer();
//attach listener
mPlayer.setOnPlayerEventListener(mInternalPlayerEventListener);
mPlayer.setOnErrorEventListener(mInternalErrorEventListener);
//init style setter.
mStyleSetter = new StyleSetter(this);
mSuperContainer = onCreateSuperContainer(context);
mSuperContainer.setStateGetter(mInternalStateGetter);
mSuperContainer.setOnReceiverEventListener(mInternalReceiverEventListener);
addView(mSuperContainer,
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
}
具体来分析setOnPlayerEventListener、setOnErrorEventListener和setOnReceiverEventListener这三个事件监听器方法。
其中:setOnPlayerEventListener和setOnErrorEventListener属于AVPlayer;
setOnReceiverEventListener属于SuperContainer。
public final class AVPlayer implements IPlayer{
// 播放事件监听器
private OnPlayerEventListener mOnPlayerEventListener;
// 错误事件监听器
private OnErrorEventListener mOnErrorEventListener;
@Override
public void setOnPlayerEventListener(OnPlayerEventListener onPlayerEventListener) {
this.mOnPlayerEventListener = onPlayerEventListener;
}
@Override
public void setOnErrorEventListener(OnErrorEventListener onErrorEventListener) {
this.mOnErrorEventListener = onErrorEventListener;
}
}
public class SuperContainer extends FrameLayout implements OnTouchGestureListener {
// 接收器事件监听器
private OnReceiverEventListener mOnReceiverEventListener;
public void setOnReceiverEventListener(OnReceiverEventListener onReceiverEventListener) {
this.mOnReceiverEventListener = onReceiverEventListener;
}
}
具体看一下OnPlayerEventListener、OnErrorEventListener和OnReceiverEventListener这三个接口:
public interface OnPlayerEventListener {
// -990开头的播放代码
void onPlayerEvent(int eventCode, Bundle bundle);
}
public interface OnErrorEventListener {
// -880开头的错误代码
void onErrorEvent(int eventCode, Bundle bundle);
}
public interface OnReceiverEventListener {
void onReceiverEvent(int eventCode, Bundle bundle);
}
具体阅读OnPlayerEventListener
OnPlayerEventListener接口具体实现在BaseVideoView和AVPlayer中:
public class BaseVideoView extends FrameLayout implements IVideoView, IStyleSetter {
private OnPlayerEventListener mInternalPlayerEventListener =
new OnPlayerEventListener() {
@Override
public void onPlayerEvent(int eventCode, Bundle bundle) {
switch (eventCode){
// 播放器尺寸改变
case OnPlayerEventListener.PLAYER_EVENT_ON_VIDEO_SIZE_CHANGE:
if(bundle!=null){
mVideoWidth = bundle.getInt(EventKey.INT_ARG1);
mVideoHeight = bundle.getInt(EventKey.INT_ARG2);
mVideoSarNum = bundle.getInt(EventKey.INT_ARG3);
mVideoSarDen = bundle.getInt(EventKey.INT_ARG4);
PLog.d(TAG,"onVideoSizeChange : videoWidth = " + mVideoWidth
+ ", videoHeight = " + mVideoHeight
+ ", videoSarNum = " + mVideoSarNum
+ ", videoSarDen = " + mVideoSarDen);
if(mRender!=null){
//update video size
mRender.updateVideoSize(mVideoWidth, mVideoHeight);
//update video sarNum,sarDen
mRender.setVideoSampleAspectRatio(mVideoSarNum, mVideoSarDen);
}
}
break;
// 播放器旋转
case OnPlayerEventListener.PLAYER_EVENT_ON_VIDEO_ROTATION_CHANGED:
if(bundle!=null){
//if rotation change need update render.
mVideoRotation = bundle.getInt(EventKey.INT_DATA);
PLog.d(TAG,"onVideoRotationChange : videoRotation = " + mVideoRotation);
if(mRender!=null)
mRender.setVideoRotation(mVideoRotation);
}
break;
// 准备好绑定到SurfaceView上
case OnPlayerEventListener.PLAYER_EVENT_ON_PREPARED:
if(bundle!=null && mRender!=null){
mVideoWidth = bundle.getInt(EventKey.INT_ARG1);
mVideoHeight = bundle.getInt(EventKey.INT_ARG2);
mRender.updateVideoSize(mVideoWidth, mVideoHeight);
}
bindRenderHolder(mRenderHolder);
break;
// 缓存开始
case OnPlayerEventListener.PLAYER_EVENT_ON_BUFFERING_START:
isBuffering = true;
break;
// 缓存结束
case OnPlayerEventListener.PLAYER_EVENT_ON_BUFFERING_END:
isBuffering = false;
break;
}
if(mOnPlayerEventListener!=null)
mOnPlayerEventListener.onPlayerEvent(eventCode, bundle);
//last dispatch event , because bundle will be recycle after dispatch.
mSuperContainer.dispatchPlayEvent(eventCode, bundle);
}
};
}
public final class AVPlayer implements IPlayer{
private OnPlayerEventListener mInternalPlayerEventListener =
new OnPlayerEventListener() {
@Override
public void onPlayerEvent(int eventCode, Bundle bundle) {
mTimerCounterProxy.proxyPlayEvent(eventCode, bundle);
// 准备开始播放
if(eventCode==OnPlayerEventListener.PLAYER_EVENT_ON_PREPARED){
//when prepared set volume value
if(mVolumeLeft >= 0 || mVolumeRight >= 0){
mInternalPlayer.setVolume(mVolumeLeft, mVolumeRight);
}
// 播放结束
}else if(eventCode==OnPlayerEventListener.PLAYER_EVENT_ON_PLAY_COMPLETE){
int duration = getDuration();
int bufferPercentage = getBufferPercentage();
//check valid data.
if(duration <= 0 && !isLive())
return;
onTimerUpdateEvent(duration, duration, bufferPercentage);
}
if(isPlayRecordOpen())
mRecordProxyPlayer.onPlayerEvent(eventCode, bundle);
callBackPlayEventListener(eventCode, bundle);
}
};
}
再具体到播放和暂停两个事件的处理
我们回到OnPlayerEventListener接口代码中:
public interface OnPlayerEventListener {
/**
* when you call {@link IPlayer#start()}
*/
int PLAYER_EVENT_ON_START = -99004;
/**
* when you call {@link IPlayer#pause()}
*/
int PLAYER_EVENT_ON_PAUSE = -99005;
void onPlayerEvent(int eventCode, Bundle bundle);
}
再ExoMediaPlayer 类中使用到了PLAYER_EVENT_ON_START和PLAYER_EVENT_ON_PAUSE两个参数。
public class ExoMediaPlayer extends BaseInternalPlayer {
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
// 视频不处于正在准备状态
if(!isPreparing){
// 是否打开即播放
if(playWhenReady){
updateStatus(IPlayer.STATE_STARTED);
// 提交恢复播放事件
submitPlayerEvent(OnPlayerEventListener.PLAYER_EVENT_ON_RESUME, null);
}else{
updateStatus(IPlayer.STATE_PAUSED);
// 提交暂停播放事件
submitPlayerEvent(OnPlayerEventListener.PLAYER_EVENT_ON_PAUSE, null);
}
}
// 视频处于正在准备状态
if(isPreparing){
switch (playbackState){
// 准备完毕
case Player.STATE_READY:
isPreparing = false;
Format format = mInternalPlayer.getVideoFormat();
Bundle bundle = BundlePool.obtain();
if(format!=null){
bundle.putInt(EventKey.INT_ARG1, format.width);
bundle.putInt(EventKey.INT_ARG2, format.height);
}
updateStatus(IPlayer.STATE_PREPARED);
// 提交准备播放事件
submitPlayerEvent(OnPlayerEventListener.PLAYER_EVENT_ON_PREPARED, bundle);
if(playWhenReady){
updateStatus(STATE_STARTED);
// 提交开始播放事件
submitPlayerEvent(OnPlayerEventListener.PLAYER_EVENT_ON_START, null);
}
if(mStartPos > 0){
mInternalPlayer.seekTo(mStartPos);
mStartPos = -1;
}
break;
}
}
}
}
上述代码的核心方法BaseInternalPlayer#submitPlayerEvent():
public abstract class BaseInternalPlayer implements IPlayer {
private OnPlayerEventListener mOnPlayerEventListener;
// 提交播放器事件
protected final void submitPlayerEvent(int eventCode, Bundle bundle){
if(mOnPlayerEventListener!=null)
mOnPlayerEventListener.onPlayerEvent(eventCode, bundle);
}
}
查看对于接口OnPlayerEventListener#onPlayerEvent()方法,对于PLAYER_EVENT_ON_START和PLAYER_EVENT_ON_PAUSE两种事件的具体反应。
从播放/暂停按钮入手
播放/暂停的drawable:selector_play_state.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true">
<bitmap android:src="@mipmap/ic_video_player_btn_play"/>
</item>
<item>
<bitmap android:src="@mipmap/ic_video_player_btn_pause"/>
</item>
</selector>
哪里使用了上述selector呢?layout_controller_cover.xml
<ImageView
android:id="@+id/cover_player_controller_image_view_play_state"
android:layout_width="wrap_content"
android:layout_height="16dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:scaleType="centerInside"
android:src="@drawable/selector_play_state"/>
ControllerCover里面有一个播放/暂停按钮。
public class ControllerCover extends BaseCover implements OnTimerUpdateListener, OnTouchGestureListener{
@BindView(R.id.cover_player_controller_image_view_play_state)
ImageView mStateIcon;
public void onViewClick(View view){
switch (view.getId()){
case R.id.cover_player_controller_image_view_play_state:
boolean selected = mStateIcon.isSelected();
if(selected){
requestResume(null);
}else{
requestPause(null);
}
mStateIcon.setSelected(!selected);
break;
case
}
}
}
上述代码中requestResume()和requestPause()两个方法源自于BaseCover类:
public abstract class BaseCover extends BaseReceiver implements
ICover, ICoverHandle, View.OnAttachStateChangeListener {
@Override
public final void requestResume(Bundle bundle) {
notifyReceiverEvent(InterEvent.CODE_REQUEST_RESUME, bundle);
}
@Override
public final void requestSeek(Bundle bundle) {
notifyReceiverEvent(InterEvent.CODE_REQUEST_SEEK, bundle);
}
}
上述代码中notifyReceiverEvent()方法源自于类BaseReceiver:
public abstract class BaseReceiver implements IReceiver, StateGetter {
private Context mContext;
private OnReceiverEventListener mOnReceiverEventListener;
protected final void notifyReceiverEvent(int eventCode, Bundle bundle){
if(mOnReceiverEventListener!=null)
mOnReceiverEventListener.onReceiverEvent(eventCode, bundle);
}
}
上述代码中的onReceiverEvent()方法源自于接口onReceiverEvent
public interface OnReceiverEventListener {
void onReceiverEvent(int eventCode, Bundle bundle);
}
返回寻找onReceiverEvent的实现类RelationAssist:
public final class RelationAssist implements AssistPlay {
private OnReceiverEventListener mOnReceiverEventListener;
private OnAssistPlayEventHandler mOnEventAssistHandler;
private OnReceiverEventListener mInternalReceiverEventListener =
new OnReceiverEventListener() {
@Override
public void onReceiverEvent(int eventCode, Bundle bundle) {
if(eventCode == InterEvent.CODE_REQUEST_NOTIFY_TIMER){
mPlayer.setUseTimerProxy(true);
}else if(eventCode == InterEvent.CODE_REQUEST_STOP_TIMER){
mPlayer.setUseTimerProxy(false);
}
//if setting AssistEventHandler, call back it to handle.
if(mOnEventAssistHandler !=null)
mOnEventAssistHandler.onAssistHandle(RelationAssist.this, eventCode, bundle);
if(mOnReceiverEventListener!=null)
mOnReceiverEventListener.onReceiverEvent(eventCode, bundle);
}
};
}
事实上是通过OnAssistPlayEventHandler#onAssistHandle()方法实现播放/暂停:
public abstract class BaseEventAssistHandler<T> implements OnEventAssistHandler<T> {
@Override
public void onAssistHandle(T assist, int eventCode, Bundle bundle) {
switch (eventCode){
case InterEvent.CODE_REQUEST_PAUSE:
requestPause(assist, bundle);
break;
case InterEvent.CODE_REQUEST_RESUME:
requestResume(assist, bundle);
break;
}
}
}
类OnAssistPlayEventHandler源码:
public class OnAssistPlayEventHandler extends BaseEventAssistHandler<AssistPlay> {
@Override
public void requestPause(BaseVideoView videoView, Bundle bundle) {
if(isInPlaybackState(videoView)){
videoView.pause();
}else{
videoView.stop();
}
}
@Override
public void requestResume(BaseVideoView videoView, Bundle bundle) {
if(isInPlaybackState(videoView)){
videoView.resume();
}else{
requestRetry(videoView, bundle);
}
}
}
上述代码播放/暂停事件流程图如下:
暂停播放事件流程.png
BaseVideoView中含有OnReceiverEventListener和OnVideoViewEventHandler
public class BaseVideoView extends FrameLayout implements IVideoView, IStyleSetter {
private OnReceiverEventListener mOnReceiverEventListener;
private OnVideoViewEventHandler mEventAssistHandler;
private OnReceiverEventListener mInternalReceiverEventListener =
new OnReceiverEventListener() {
@Override
public void onReceiverEvent(int eventCode, Bundle bundle) {
if(eventCode == InterEvent.CODE_REQUEST_NOTIFY_TIMER){
mPlayer.setUseTimerProxy(true);
}else if(eventCode == InterEvent.CODE_REQUEST_STOP_TIMER){
mPlayer.setUseTimerProxy(false);
}
if(mEventAssistHandler!=null)
mEventAssistHandler.onAssistHandle(BaseVideoView.this, eventCode, bundle);
if(mOnReceiverEventListener!=null)
mOnReceiverEventListener.onReceiverEvent(eventCode, bundle);
}
};
}
OnVideoViewEventHandler
首先分析OnVideoViewEventHandler#onAssistHandle()方法。
OnVideoViewEventHandler继承抽象类BaseEventAssistHandler实现接口OnEventAssistHandler
接口OnEventAssistHandler源码:
public interface OnEventAssistHandler<T> {
void onAssistHandle(T assist, int eventCode, Bundle bundle);
void requestPause(T assist, Bundle bundle);
void requestResume(T assist, Bundle bundle);
}
抽象类BaseEventAssistHandler源码:
public abstract class BaseEventAssistHandler<T> implements OnEventAssistHandler<T> {
@Override
public void onAssistHandle(T assist, int eventCode, Bundle bundle) {
switch (eventCode){
case InterEvent.CODE_REQUEST_PAUSE:
requestPause(assist, bundle);
break;
case InterEvent.CODE_REQUEST_RESUME:
requestResume(assist, bundle);
break;
}
}
}
类OnVideoViewEventHandler 源码:
public class OnVideoViewEventHandler extends BaseEventAssistHandler<BaseVideoView> {
@Override
public void requestPause(BaseVideoView videoView, Bundle bundle) {
if(isInPlaybackState(videoView)){
videoView.pause();
}else{
videoView.stop();
}
}
@Override
public void requestResume(BaseVideoView videoView, Bundle bundle) {
if(isInPlaybackState(videoView)){
videoView.resume();
}else{
requestRetry(videoView, bundle);
}
}
}
网友评论