|
@@ -140,574 +140,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
-### 04.VideoPlayer如何实现
|
|
|
-- 代码如下所示,省略了部分代码,具体看demo
|
|
|
- ``` java
|
|
|
- public class VideoPlayer<P extends AbstractVideoPlayer> extends FrameLayout
|
|
|
- implements InterVideoPlayer, VideoPlayerListener {
|
|
|
-
|
|
|
- private Context mContext;
|
|
|
- /**
|
|
|
- * 播放器
|
|
|
- */
|
|
|
- protected P mMediaPlayer;
|
|
|
- /**
|
|
|
- * 实例化播放核心
|
|
|
- */
|
|
|
- protected PlayerFactory<P> mPlayerFactory;
|
|
|
- /**
|
|
|
- * 控制器
|
|
|
- */
|
|
|
- @Nullable
|
|
|
- protected BaseVideoController mVideoController;
|
|
|
- /**
|
|
|
- * 真正承载播放器视图的容器
|
|
|
- */
|
|
|
- protected FrameLayout mPlayerContainer;
|
|
|
-
|
|
|
- public VideoPlayer(@NonNull Context context) {
|
|
|
- this(context, null);
|
|
|
- }
|
|
|
-
|
|
|
- public VideoPlayer(@NonNull Context context, @Nullable AttributeSet attrs) {
|
|
|
- this(context, attrs, 0);
|
|
|
- }
|
|
|
-
|
|
|
- public VideoPlayer(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
|
|
- super(context, attrs, defStyleAttr);
|
|
|
- mContext = context;
|
|
|
- init(attrs);
|
|
|
- }
|
|
|
-
|
|
|
- private void init(AttributeSet attrs) {
|
|
|
- BaseToast.init(mContext.getApplicationContext());
|
|
|
- //读取全局配置
|
|
|
- initConfig();
|
|
|
- //读取xml中的配置,并综合全局配置
|
|
|
- initAttrs(attrs);
|
|
|
- initView();
|
|
|
- }
|
|
|
-
|
|
|
- private void initConfig() {
|
|
|
- VideoPlayerConfig config = VideoViewManager.getConfig();
|
|
|
- mEnableAudioFocus = config.mEnableAudioFocus;
|
|
|
- mProgressManager = config.mProgressManager;
|
|
|
- mPlayerFactory = config.mPlayerFactory;
|
|
|
- mCurrentScreenScaleType = config.mScreenScaleType;
|
|
|
- mRenderViewFactory = config.mRenderViewFactory;
|
|
|
- //设置是否打印日志
|
|
|
- VideoLogUtils.setIsLog(config.mIsEnableLog);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- protected Parcelable onSaveInstanceState() {
|
|
|
- VideoLogUtils.d("onSaveInstanceState: " + mCurrentPosition);
|
|
|
- //activity切到后台后可能被系统回收,故在此处进行进度保存
|
|
|
- saveProgress();
|
|
|
- return super.onSaveInstanceState();
|
|
|
- }
|
|
|
-
|
|
|
- private void initAttrs(AttributeSet attrs) {
|
|
|
- TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.VideoPlayer);
|
|
|
- mEnableAudioFocus = a.getBoolean(R.styleable.VideoPlayer_enableAudioFocus, mEnableAudioFocus);
|
|
|
- mIsLooping = a.getBoolean(R.styleable.VideoPlayer_looping, false);
|
|
|
- mCurrentScreenScaleType = a.getInt(R.styleable.VideoPlayer_screenScaleType, mCurrentScreenScaleType);
|
|
|
- mPlayerBackgroundColor = a.getColor(R.styleable.VideoPlayer_playerBackgroundColor, Color.BLACK);
|
|
|
- a.recycle();
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 初始化播放器视图
|
|
|
- */
|
|
|
- protected void initView() {
|
|
|
- mPlayerContainer = new FrameLayout(getContext());
|
|
|
- //设置背景颜色,目前设置为纯黑色
|
|
|
- mPlayerContainer.setBackgroundColor(mPlayerBackgroundColor);
|
|
|
- LayoutParams params = new LayoutParams(
|
|
|
- ViewGroup.LayoutParams.MATCH_PARENT,
|
|
|
- ViewGroup.LayoutParams.MATCH_PARENT);
|
|
|
- //将布局添加到该视图中
|
|
|
- this.addView(mPlayerContainer, params);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 设置控制器,传null表示移除控制器
|
|
|
- * @param mediaController controller
|
|
|
- */
|
|
|
- public void setController(@Nullable BaseVideoController mediaController) {
|
|
|
- mPlayerContainer.removeView(mVideoController);
|
|
|
- mVideoController = mediaController;
|
|
|
- if (mediaController != null) {
|
|
|
- mediaController.setMediaPlayer(this);
|
|
|
- LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
|
|
|
- ViewGroup.LayoutParams.MATCH_PARENT);
|
|
|
- mPlayerContainer.addView(mVideoController, params);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 开始播放,注意:调用此方法后必须调用{@link #release()}释放播放器,否则会导致内存泄漏
|
|
|
- */
|
|
|
- @Override
|
|
|
- public void start() {
|
|
|
- if (mVideoController==null){
|
|
|
- //在调用start方法前,请先初始化视频控制器,调用setController方法
|
|
|
- throw new VideoException(VideoException.CODE_NOT_SET_CONTROLLER,
|
|
|
- "Controller must not be null , please setController first");
|
|
|
- }
|
|
|
- boolean isStarted = false;
|
|
|
- if (isInIdleState() || isInStartAbortState()) {
|
|
|
- isStarted = startPlay();
|
|
|
- } else if (isInPlaybackState()) {
|
|
|
- startInPlaybackState();
|
|
|
- isStarted = true;
|
|
|
- }
|
|
|
- if (isStarted) {
|
|
|
- mPlayerContainer.setKeepScreenOn(true);
|
|
|
- if (mAudioFocusHelper != null){
|
|
|
- mAudioFocusHelper.requestFocus();
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 第一次播放
|
|
|
- * @return 是否成功开始播放
|
|
|
- */
|
|
|
- protected boolean startPlay() {
|
|
|
- //如果要显示移动网络提示则不继续播放
|
|
|
- if (showNetWarning()) {
|
|
|
- //中止播放
|
|
|
- setPlayState(ConstantKeys.CurrentState.STATE_START_ABORT);
|
|
|
- return false;
|
|
|
- }
|
|
|
- //监听音频焦点改变
|
|
|
- if (mEnableAudioFocus) {
|
|
|
- mAudioFocusHelper = new AudioFocusHelper(this);
|
|
|
- }
|
|
|
- //读取播放进度
|
|
|
- if (mProgressManager != null) {
|
|
|
- mCurrentPosition = mProgressManager.getSavedProgress(mUrl);
|
|
|
- }
|
|
|
- initPlayer();
|
|
|
- addDisplay();
|
|
|
- startPrepare(false);
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- /**
|
|
|
- * 初始化播放器
|
|
|
- */
|
|
|
- protected void initPlayer() {
|
|
|
- //通过工厂模式创建对象
|
|
|
- mMediaPlayer = mPlayerFactory.createPlayer(mContext);
|
|
|
- mMediaPlayer.setPlayerEventListener(this);
|
|
|
- setInitOptions();
|
|
|
- mMediaPlayer.initPlayer();
|
|
|
- setOptions();
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 初始化视频渲染View
|
|
|
- */
|
|
|
- protected void addDisplay() {
|
|
|
- if (mRenderView != null) {
|
|
|
- mPlayerContainer.removeView(mRenderView.getView());
|
|
|
- mRenderView.release();
|
|
|
- }
|
|
|
- //创建TextureView对象
|
|
|
- mRenderView = mRenderViewFactory.createRenderView(mContext);
|
|
|
- //绑定mMediaPlayer对象
|
|
|
- mRenderView.attachToPlayer(mMediaPlayer);
|
|
|
- LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
|
|
|
- ViewGroup.LayoutParams.MATCH_PARENT, Gravity.CENTER);
|
|
|
- mPlayerContainer.addView(mRenderView.getView(), 0, params);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 开始准备播放(直接播放)
|
|
|
- */
|
|
|
- protected void startPrepare(boolean reset) {
|
|
|
- if (reset) {
|
|
|
- mMediaPlayer.reset();
|
|
|
- //重新设置option,media player reset之后,option会失效
|
|
|
- setOptions();
|
|
|
- }
|
|
|
- if (prepareDataSource()) {
|
|
|
- mMediaPlayer.prepareAsync();
|
|
|
- setPlayState(ConstantKeys.CurrentState.STATE_PREPARING);
|
|
|
- setPlayerState(isFullScreen() ? ConstantKeys.PlayMode.MODE_FULL_SCREEN :
|
|
|
- isTinyScreen() ? ConstantKeys.PlayMode.MODE_TINY_WINDOW : ConstantKeys.PlayMode.MODE_NORMAL);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 设置播放数据
|
|
|
- * @return 播放数据是否设置成功
|
|
|
- */
|
|
|
- protected boolean prepareDataSource() {
|
|
|
- if (mAssetFileDescriptor != null) {
|
|
|
- mMediaPlayer.setDataSource(mAssetFileDescriptor);
|
|
|
- return true;
|
|
|
- } else if (!TextUtils.isEmpty(mUrl)) {
|
|
|
- mMediaPlayer.setDataSource(mUrl, mHeaders);
|
|
|
- return true;
|
|
|
- }
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 向Controller设置播放状态,用于控制Controller的ui展示
|
|
|
- * 这里使用注解限定符,不要使用1,2这种直观数字,不方便知道意思
|
|
|
- * 播放状态,主要是指播放器的各种状态
|
|
|
- * -1 播放错误
|
|
|
- * 0 播放未开始
|
|
|
- * 1 播放准备中
|
|
|
- * 2 播放准备就绪
|
|
|
- * 3 正在播放
|
|
|
- * 4 暂停播放
|
|
|
- * 5 正在缓冲(播放器正在播放时,缓冲区数据不足,进行缓冲,缓冲区数据足够后恢复播放)
|
|
|
- * 6 暂停缓冲(播放器正在播放时,缓冲区数据不足,进行缓冲,此时暂停播放器,继续缓冲,缓冲区数据足够后恢复暂停
|
|
|
- * 7 播放完成
|
|
|
- * 8 开始播放中止
|
|
|
- */
|
|
|
- protected void setPlayState(@ConstantKeys.CurrentStateType int playState) {
|
|
|
- mCurrentPlayState = playState;
|
|
|
- if (mVideoController != null) {
|
|
|
- mVideoController.setPlayState(playState);
|
|
|
- }
|
|
|
- if (mOnStateChangeListeners != null) {
|
|
|
- for (OnVideoStateListener l : PlayerUtils.getSnapshot(mOnStateChangeListeners)) {
|
|
|
- if (l != null) {
|
|
|
- l.onPlayStateChanged(playState);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 向Controller设置播放器状态,包含全屏状态和非全屏状态
|
|
|
- * 播放模式
|
|
|
- * 普通模式,小窗口模式,正常模式三种其中一种
|
|
|
- * MODE_NORMAL 普通模式
|
|
|
- * MODE_FULL_SCREEN 全屏模式
|
|
|
- * MODE_TINY_WINDOW 小屏模式
|
|
|
- */
|
|
|
- protected void setPlayerState(@ConstantKeys.PlayModeType int playerState) {
|
|
|
- mCurrentPlayerState = playerState;
|
|
|
- if (mVideoController != null) {
|
|
|
- mVideoController.setPlayerState(playerState);
|
|
|
- }
|
|
|
- if (mOnStateChangeListeners != null) {
|
|
|
- for (OnVideoStateListener l : PlayerUtils.getSnapshot(mOnStateChangeListeners)) {
|
|
|
- if (l != null) {
|
|
|
- l.onPlayerStateChanged(playerState);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * OnStateChangeListener的空实现。用的时候只需要重写需要的方法
|
|
|
- */
|
|
|
- public static class SimpleOnStateChangeListener implements OnVideoStateListener {
|
|
|
- @Override
|
|
|
- public void onPlayerStateChanged(@ConstantKeys.PlayModeType int playerState) {}
|
|
|
- @Override
|
|
|
- public void onPlayStateChanged(int playState) {}
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 添加一个播放状态监听器,播放状态发生变化时将会调用。
|
|
|
- */
|
|
|
- public void addOnStateChangeListener(@NonNull OnVideoStateListener listener) {
|
|
|
- if (mOnStateChangeListeners == null) {
|
|
|
- mOnStateChangeListeners = new ArrayList<>();
|
|
|
- }
|
|
|
- mOnStateChangeListeners.add(listener);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 移除某个播放状态监听
|
|
|
- */
|
|
|
- public void removeOnStateChangeListener(@NonNull OnVideoStateListener listener) {
|
|
|
- if (mOnStateChangeListeners != null) {
|
|
|
- mOnStateChangeListeners.remove(listener);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 设置一个播放状态监听器,播放状态发生变化时将会调用,
|
|
|
- * 如果你想同时设置多个监听器,推荐 {@link #addOnStateChangeListener(OnVideoStateListener)}。
|
|
|
- */
|
|
|
- public void setOnStateChangeListener(@NonNull OnVideoStateListener listener) {
|
|
|
- if (mOnStateChangeListeners == null) {
|
|
|
- mOnStateChangeListeners = new ArrayList<>();
|
|
|
- } else {
|
|
|
- mOnStateChangeListeners.clear();
|
|
|
- }
|
|
|
- mOnStateChangeListeners.add(listener);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 移除所有播放状态监听
|
|
|
- */
|
|
|
- public void clearOnStateChangeListeners() {
|
|
|
- if (mOnStateChangeListeners != null) {
|
|
|
- mOnStateChangeListeners.clear();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 改变返回键逻辑,用于activity
|
|
|
- */
|
|
|
- public boolean onBackPressed() {
|
|
|
- return mVideoController != null && mVideoController.onBackPressed();
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
- ```
|
|
|
-
|
|
|
-
|
|
|
-### 05.VideoController实现
|
|
|
-- 代码如下所示,代码太长,省略部分代码,具体看demo
|
|
|
- ``` java
|
|
|
- public abstract class BaseVideoController extends FrameLayout implements InterVideoController,
|
|
|
- OrientationHelper.OnOrientationChangeListener {
|
|
|
-
|
|
|
- //播放器包装类,集合了MediaPlayerControl的api和IVideoController的api
|
|
|
- protected ControlWrapper mControlWrapper;
|
|
|
-
|
|
|
- public BaseVideoController(@NonNull Context context) {
|
|
|
- //创建
|
|
|
- this(context, null);
|
|
|
- }
|
|
|
-
|
|
|
- public BaseVideoController(@NonNull Context context, @Nullable AttributeSet attrs) {
|
|
|
- //创建
|
|
|
- this(context, attrs, 0);
|
|
|
- }
|
|
|
-
|
|
|
- public BaseVideoController(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
|
|
|
- super(context, attrs, defStyleAttr);
|
|
|
- initView(context);
|
|
|
- }
|
|
|
-
|
|
|
- protected void initView(Context context) {
|
|
|
- if (getLayoutId() != 0) {
|
|
|
- LayoutInflater.from(getContext()).inflate(getLayoutId(), this, true);
|
|
|
- }
|
|
|
- mOrientationHelper = new OrientationHelper(context.getApplicationContext());
|
|
|
- mEnableOrientation = VideoViewManager.getConfig().mEnableOrientation;
|
|
|
- mAdaptCutout = VideoViewManager.getConfig().mAdaptCutout;
|
|
|
- mShowAnim = new AlphaAnimation(0f, 1f);
|
|
|
- mShowAnim.setDuration(300);
|
|
|
- mHideAnim = new AlphaAnimation(1f, 0f);
|
|
|
- mHideAnim.setDuration(300);
|
|
|
- mActivity = PlayerUtils.scanForActivity(context);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 设置控制器布局文件,子类必须实现
|
|
|
- */
|
|
|
- protected abstract int getLayoutId();
|
|
|
-
|
|
|
- /**
|
|
|
- * 重要:此方法用于将{@link VideoPlayer} 和控制器绑定
|
|
|
- */
|
|
|
- @CallSuper
|
|
|
- public void setMediaPlayer(InterVideoPlayer mediaPlayer) {
|
|
|
- mControlWrapper = new ControlWrapper(mediaPlayer, this);
|
|
|
- //绑定ControlComponent和Controller
|
|
|
- for (Map.Entry<InterControlView, Boolean> next : mControlComponents.entrySet()) {
|
|
|
- InterControlView component = next.getKey();
|
|
|
- component.attach(mControlWrapper);
|
|
|
- }
|
|
|
- //开始监听设备方向
|
|
|
- mOrientationHelper.setOnOrientationChangeListener(this);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 添加控制组件,最后面添加的在最下面,合理组织添加顺序,可让ControlComponent位于不同的层级
|
|
|
- */
|
|
|
- public void addControlComponent(InterControlView... component) {
|
|
|
- for (InterControlView item : component) {
|
|
|
- addControlComponent(item, false);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 添加控制组件,最后面添加的在最下面,合理组织添加顺序,可让ControlComponent位于不同的层级
|
|
|
- *
|
|
|
- * @param isPrivate 是否为独有的组件,如果是就不添加到控制器中
|
|
|
- */
|
|
|
- public void addControlComponent(InterControlView component, boolean isPrivate) {
|
|
|
- mControlComponents.put(component, isPrivate);
|
|
|
- if (mControlWrapper != null) {
|
|
|
- component.attach(mControlWrapper);
|
|
|
- }
|
|
|
- View view = component.getView();
|
|
|
- if (view != null && !isPrivate) {
|
|
|
- addView(view, 0);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 移除控制组件
|
|
|
- */
|
|
|
- public void removeControlComponent(InterControlView component) {
|
|
|
- removeView(component.getView());
|
|
|
- mControlComponents.remove(component);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 移除所有的组件
|
|
|
- */
|
|
|
- public void removeAllControlComponent() {
|
|
|
- for (Map.Entry<InterControlView, Boolean> next : mControlComponents.entrySet()) {
|
|
|
- removeView(next.getKey().getView());
|
|
|
- }
|
|
|
- mControlComponents.clear();
|
|
|
- }
|
|
|
-
|
|
|
- public void removeAllPrivateComponents() {
|
|
|
- Iterator<Map.Entry<InterControlView, Boolean>> it = mControlComponents.entrySet().iterator();
|
|
|
- while (it.hasNext()) {
|
|
|
- Map.Entry<InterControlView, Boolean> next = it.next();
|
|
|
- if (next.getValue()) {
|
|
|
- it.remove();
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * {@link VideoPlayer}调用此方法向控制器设置播放状态。
|
|
|
- * 这里使用注解限定符,不要使用1,2这种直观数字,不方便知道意思
|
|
|
- * 播放状态,主要是指播放器的各种状态
|
|
|
- * -1 播放错误
|
|
|
- * 0 播放未开始
|
|
|
- * 1 播放准备中
|
|
|
- * 2 播放准备就绪
|
|
|
- * 3 正在播放
|
|
|
- * 4 暂停播放
|
|
|
- * 5 正在缓冲(播放器正在播放时,缓冲区数据不足,进行缓冲,缓冲区数据足够后恢复播放)
|
|
|
- * 6 暂停缓冲(播放器正在播放时,缓冲区数据不足,进行缓冲,此时暂停播放器,继续缓冲,缓冲区数据足够后恢复暂停
|
|
|
- * 7 播放完成
|
|
|
- * 8 开始播放中止
|
|
|
- */
|
|
|
- @CallSuper
|
|
|
- public void setPlayState(@ConstantKeys.CurrentStateType int playState) {
|
|
|
- //设置播放器的状态
|
|
|
- handlePlayStateChanged(playState);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * {@link VideoPlayer}调用此方法向控制器设置播放器状态
|
|
|
- * 播放模式
|
|
|
- * 普通模式,小窗口模式,正常模式三种其中一种
|
|
|
- * MODE_NORMAL 普通模式
|
|
|
- * MODE_FULL_SCREEN 全屏模式
|
|
|
- * MODE_TINY_WINDOW 小屏模式
|
|
|
- */
|
|
|
- @CallSuper
|
|
|
- public void setPlayerState(@ConstantKeys.PlayModeType final int playerState) {
|
|
|
- //调用此方法向控制器设置播放器状态
|
|
|
- handlePlayerStateChanged(playerState);
|
|
|
- }
|
|
|
-
|
|
|
- private void handleVisibilityChanged(boolean isVisible, Animation anim) {
|
|
|
- if (!mIsLocked) {
|
|
|
- //没锁住时才向ControlComponent下发此事件
|
|
|
- for (Map.Entry<InterControlView, Boolean> next : mControlComponents.entrySet()) {
|
|
|
- InterControlView component = next.getKey();
|
|
|
- component.onVisibilityChanged(isVisible, anim);
|
|
|
- }
|
|
|
- }
|
|
|
- onVisibilityChanged(isVisible, anim);
|
|
|
- }
|
|
|
-
|
|
|
- private void handlePlayStateChanged(int playState) {
|
|
|
- for (Map.Entry<InterControlView, Boolean> next : mControlComponents.entrySet()) {
|
|
|
- InterControlView component = next.getKey();
|
|
|
- component.onPlayStateChanged(playState);
|
|
|
- }
|
|
|
- onPlayStateChanged(playState);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 子类重写此方法并在其中更新控制器在不同播放状态下的ui
|
|
|
- */
|
|
|
- @CallSuper
|
|
|
- protected void onPlayStateChanged(int playState) {
|
|
|
- switch (playState) {
|
|
|
- case ConstantKeys.CurrentState.STATE_IDLE:
|
|
|
- mOrientationHelper.disable();
|
|
|
- mOrientation = 0;
|
|
|
- mIsLocked = false;
|
|
|
- mShowing = false;
|
|
|
- removeAllPrivateComponents();
|
|
|
- break;
|
|
|
- case ConstantKeys.CurrentState.STATE_BUFFERING_PLAYING:
|
|
|
- mIsLocked = false;
|
|
|
- mShowing = false;
|
|
|
- break;
|
|
|
- case ConstantKeys.CurrentState.STATE_ERROR:
|
|
|
- mShowing = false;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 播放器状态改变
|
|
|
- * @param playerState 播放器状态
|
|
|
- */
|
|
|
- private void handlePlayerStateChanged(int playerState) {
|
|
|
- for (Map.Entry<InterControlView, Boolean> next : mControlComponents.entrySet()) {
|
|
|
- InterControlView component = next.getKey();
|
|
|
- component.onPlayerStateChanged(playerState);
|
|
|
- }
|
|
|
- onPlayerStateChanged(playerState);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 子类重写此方法并在其中更新控制器在不同播放器状态下的ui
|
|
|
- * 普通模式,小窗口模式,正常模式三种其中一种
|
|
|
- * MODE_NORMAL 普通模式
|
|
|
- * MODE_FULL_SCREEN 全屏模式
|
|
|
- * MODE_TINY_WINDOW 小屏模式
|
|
|
- */
|
|
|
- @CallSuper
|
|
|
- protected void onPlayerStateChanged(@ConstantKeys.PlayMode int playerState) {
|
|
|
- switch (playerState) {
|
|
|
- case ConstantKeys.PlayMode.MODE_NORMAL:
|
|
|
- //视频正常播放是设置监听
|
|
|
- if (mEnableOrientation) {
|
|
|
- //检查系统是否开启自动旋转
|
|
|
- mOrientationHelper.enable();
|
|
|
- } else {
|
|
|
- //取消监听
|
|
|
- mOrientationHelper.disable();
|
|
|
- }
|
|
|
- if (hasCutout()) {
|
|
|
- StatesCutoutUtils.adaptCutoutAboveAndroidP(getContext(), false);
|
|
|
- }
|
|
|
- break;
|
|
|
- case ConstantKeys.PlayMode.MODE_FULL_SCREEN:
|
|
|
- //在全屏时强制监听设备方向
|
|
|
- mOrientationHelper.enable();
|
|
|
- if (hasCutout()) {
|
|
|
- StatesCutoutUtils.adaptCutoutAboveAndroidP(getContext(), true);
|
|
|
- }
|
|
|
- break;
|
|
|
- case ConstantKeys.PlayMode.MODE_TINY_WINDOW:
|
|
|
- //小窗口取消重力感应监听
|
|
|
- mOrientationHelper.disable();
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- ```
|
|
|
|
|
|
|
|
|
### 06.播放Player和UI通信
|