BaseVideoView.java 13 KB
package com.cnlive.gundam.video.view;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.databinding.DataBindingUtil;
import android.os.Build;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.widget.RelativeLayout;

import com.cnlive.gundam.R;
import com.cnlive.gundam.databinding.LayoutVideoViewBinding;
import com.cnlive.gundam.video.model.DataSource;
import com.cnlive.gundam.video.model.VideoModel;
import com.cnlive.libs.util.Config;
import com.cnlive.libs.util.ProbeUtil;
import com.cnlive.libs.util.SharedPreferencesHelper;
import com.cnlive.libs.video.video.VideoStatusUtil;
import com.cnlive.libs.video.video.base.IMediaPlayer;
import com.cnlive.libs.video.video.base.ISwitchVideoView;
import com.cnlive.libs.video.video.base.IVideoStatus;

/**
 * Created by gujun on 2017/4/5.
 * 这个里只是关于播放器和ugc直播播放状态的相关处理
 */

public abstract class BaseVideoView extends RelativeLayout implements
        IMediaPlayer.OnCompletionListener, IMediaPlayer.OnInfoListener,
        IMediaPlayer.OnErrorListener, IMediaPlayer.OnPlayStateListener,
        IMediaPlayer.OnSeekCompleteListener, IMediaPlayer.OnPreparedListener,
        IMediaPlayer.OnBufferingUpdateListener, ISwitchVideoView.OnSwitchVideoPreparedListener,
        ISwitchVideoView.OnSwitchVideoErrorListener, ISwitchVideoView.OnSwitchVideoCompleteListener {

    protected LayoutVideoViewBinding binding;

    //记录当前视频播放状态
    protected boolean isPlay = false;
    //当前播放器的播放进度 重试的时候从此时间播放
    private long curPlayPosition = -1;
    //prepare后是否seekTo 为了重试后seekComplete过滤
    private boolean isPrepareSeek = false;

    //播放数据
    protected VideoModel videoModel;
    //记录当前是否是直播节目
    protected static boolean isLive;
    //记录当前视频是否能播
    protected boolean canPlay = true;
    //记录当前视频状态是否结束,结束后就不再播
    protected boolean isStatusEnd = false;
    //本地缓存数据工具类
    private SharedPreferencesHelper sharedPreferencesHelper;
    //播放进度保存至本地缓存的标识前缀
    private final String CUR_PLAY_POSITION_PRE = "CurPlayPosition_";
    //保存切换码率之前的码率
    private String preRate = Config.TYPE_PLAY_RATE_2;
    //保存当前要切换的码率
    private String curRate = "";
    //记录当前是否正在切换视频
    protected boolean switchingVideoRate = false;

    private DataSource curDataSource;

    //播放器播放状态的监听
    private OnVideoViewPlayStatusListener l;

    //ugclive需要权限监听
    private OnUgcLiveStatusPermissionListener ugcLivePermissionListener;

    public BaseVideoView(Context context) {
        this(context, null);
    }

    public BaseVideoView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BaseVideoView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public void setVideoViewPlayStatus(OnVideoViewPlayStatusListener listener) {
        l = listener;
    }

    protected void init() {
        sharedPreferencesHelper = SharedPreferencesHelper.getInstance(getContext());
        binding = DataBindingUtil.inflate(LayoutInflater.from(getContext()), R.layout.layout_video_view, this, true);
        binding.videoView.setOnPreparedListener(this);
        binding.videoView.setOnInfoListener(this);
        binding.videoView.setOnErrorListener(this);
        binding.videoView.setOnCompletionListener(this);
        binding.videoView.setOnSeekCompleteListener(this);
        binding.videoView.setOnPlayStateListener(this);
        binding.videoView.setOnBufferingUpdateListener(this);
        binding.videoView.setScreenOnWhilePlaying(true);
        binding.videoView.setOnSwitchVideoPreparedListener(this);
        binding.videoView.setOnSwitchVideoErrorListener(this);
        binding.videoView.setOnSwitchVideoCompleteListener(this);
        setKeepScreenOn(true);
    }

    public void setDataSource() {
        //只有ugcLive视频才有状态监听
        if (videoModel.getType().equals(VideoView.TYPE_UGC_LIVE)) {
            if (Build.VERSION.SDK_INT >= 23) {
                int checkCallPhonePermission = ContextCompat.checkSelfPermission(getContext(), Manifest.permission.READ_PHONE_STATE);
                if (checkCallPhonePermission != PackageManager.PERMISSION_GRANTED) {
                    if (ugcLivePermissionListener != null)
                        ugcLivePermissionListener.onShouldRequestPermission();
                } else {
                    addUgcLiveStatus();
                }
            } else {
                addUgcLiveStatus();
            }
        }

        if (isLive) {
            curPlayPosition = -1;
            binding.videoView.setDataSource(curDataSource = new DataSource(videoModel.getId(), Config.TYPE_LIVE, Config.TYPE_PLAY_RATE_2));
        } else {
            curPlayPosition = sharedPreferencesHelper.getLong(CUR_PLAY_POSITION_PRE + videoModel.getId());
            binding.videoView.setDataSource(curDataSource = new DataSource(videoModel.getId(), Config.TYPE_VOD, Config.TYPE_PLAY_RATE_2));
        }

        preRate = Config.TYPE_PLAY_RATE_2;

    }

    /**
     * 设置UGC LIVE的直播状态监听
     */
    public void setUgcLiveStatusPermissionListener(OnUgcLiveStatusPermissionListener l) {
        ugcLivePermissionListener = l;
    }

    /**
     * 添加UGC LIVE的直播状态监听
     */
    public void addUgcLiveStatus() {
        VideoStatusUtil.setOnVideoPlayStatusCallback(mOnVideoStatusCallback);
        VideoStatusUtil.init(videoModel.getId());
    }

    /**
     * 设置当前播放进度
     *
     * @param curPosition
     */
    protected void setPlayPosition(long curPosition) {
        curPlayPosition = curPosition;
    }

    public void onResume() {
        if (!binding.videoView.isPlaying() && isPlay) {
            setPlayState(true);
        }
    }

    public void onPause() {
        if (binding.videoView.isPlaying()) {
            setPlayState(false);
        }
    }

    public void onDestroy() {
        binding.videoView.releaseSwitchVideo();
        boolean playing = binding.videoView.isPlaying();
        if(playing){setPlayState(false);}
        binding.videoView.release();
        VideoStatusUtil.quit();
        saveCurPlayPosition();


    }

    //保存当前播放视频的播放进度
    protected void saveCurPlayPosition() {
        if (!isLive && curDataSource != null && sharedPreferencesHelper != null) {
            sharedPreferencesHelper.setValue(CUR_PLAY_POSITION_PRE + curDataSource.getDataSourceId(), curPlayPosition);
        }
    }

    protected void retry() {
        binding.videoView.reload();
    }

    protected void replay() {
        isPrepareSeek = true;
        binding.videoView.seekTo(0);
    }

    /**
     * 设置播放状态
     *
     * @param isPlay
     */
    protected void setPlayState(boolean isPlay) {
        if (isPlay) {
            if (videoModel.getType().equals(VideoView.TYPE_UGC_LIVE)) {
                ProbeUtil.probeSDK("ugcLiveStart");

                Log.v("TestDemo","ugcLiveStart");

            } else if (videoModel.getType().equals(VideoView.TYPE_LIVE)) {
                ProbeUtil.probeSDK("pgcLiveStart");

                Log.v("TestDemo","pgcLiveStart");

            } else if (videoModel.getType().equals(VideoView.TYPE_UGC_VOD)) {
                ProbeUtil.probeSDK("ugcVodStart");

                Log.v("TestDemo","ugcVodStart");

            }
            binding.videoView.start();
        } else {
            if (videoModel.getType().equals(VideoView.TYPE_UGC_LIVE)) {
                ProbeUtil.probeSDK("ugcLiveEnd");

                Log.v("TestDemo","ugcLiveEnd");

            } else if (videoModel.getType().equals(VideoView.TYPE_LIVE)) {
                ProbeUtil.probeSDK("pgcLiveEnd");

                Log.v("TestDemo","pgcLiveEnd");

            } else if (videoModel.getType().equals(VideoView.TYPE_UGC_VOD)) {
                ProbeUtil.probeSDK("ugcVodEnd");

                Log.v("TestDemo","ugcVodEnd");

            }
            binding.videoView.pause();
        }

    }

    /**
     * 播放按钮点击
     */
    public void playBtnClick() {
        isPlay = !isPlay;
        setPlayState(isPlay);
    }

    /**
     * 切换视频码率
     *
     * @param rate
     */
    public void switchVideoRate(String rate) {
        curRate = rate;
        if (binding.controllerView != null)
            binding.controllerView.setSwitchRateType(PlayerControllerView.SWITCH_RATE_START, curRate);
        curDataSource.setRate(rate);
        if (binding.videoView != null)
            binding.videoView.switchVideo(curDataSource);
    }


//----------------------播放器相关回调 start-------------------------------

    @Override
    public void onCompletion(IMediaPlayer iMediaPlayer) {
        isPlay = false;
        setPlayState(false);
    }

    @Override
    public boolean onError(IMediaPlayer iMediaPlayer, int i, int i1) {
        isPlay = false;
        return false;
    }

    @Override
    public boolean onInfo(IMediaPlayer iMediaPlayer, int i, int i1) {
        return false;
    }

    @Override
    public void onPlayState(boolean isPlay) {
        if (l != null) l.onVideoViewPlayStatus(isPlay);
    }

    @Override
    public void onPrepared(IMediaPlayer iMediaPlayer) {
        if (curPlayPosition > 0) {
            isPrepareSeek = true;
            iMediaPlayer.seekTo(curPlayPosition);
        } else {
            if (!iMediaPlayer.getPlayState()) {
                setPlayState(true);
                isPlay = true;
            }
        }
    }

    @Override
    public void onSeekComplete(IMediaPlayer iMediaPlayer) {
        if (!isPrepareSeek) return;
        isPrepareSeek = false;
        setPlayState(true);
        isPlay = true;
    }

    @Override
    public void onBufferingUpdate(IMediaPlayer iMediaPlayer, int i) {

    }


    @Override
    public void onSwitchVideoError(IMediaPlayer iMediaPlayer, int i, int i1) {
        binding.videoView.releaseSwitchVideo();
        switchingVideoRate = false;
        //切换失败继续播切换之前的码率
        curDataSource.setRate(preRate);
        if (binding.controllerView != null) {
            binding.controllerView.setCurRate(preRate);
            binding.controllerView.setSwitchRateType(PlayerControllerView.SWITCH_RATE_ERROR, curRate);
        }
    }

    @Override
    public void onSwitchVideoComplete(IMediaPlayer iMediaPlayer) {
        switchingVideoRate = false;
        if (binding.controllerView != null)
            binding.controllerView.setSwitchRateType(PlayerControllerView.SWITCH_RATE_FINISH, curRate);
        preRate = curRate;
    }

    @Override
    public void onSwitchVideoPrepared(IMediaPlayer iMediaPlayer) {
        switchingVideoRate = true;
        if (binding.videoView != null) {
            binding.videoView.switchVideoStart(binding.videoView.getCurrentPosition());
        }
    }


//    ---------------------ugc直播状态的回调---------------------------------

    private IVideoStatus.VideoStatusCallback mOnVideoStatusCallback = new IVideoStatus.VideoStatusCallback() {
        @Override
        public void onStatusChange(int status) {
            switch (status) {
                case IVideoStatus.MEDIA_STATUS_LIVING:
                    //直播中'
                    if (!isStatusEnd) {
                        canPlay = true;
                        isPlay = true;
                        setPlayState(true);
                    }
                    break;
                case IVideoStatus.MEDIA_STATUS_LEAVE:
                    //主播暂时离开
                    if (!isStatusEnd) {
                        canPlay = false;
                        isPlay = false;
                        setPlayState(false);
                        binding.infoView.show(PlayerInfoView.SHOW_UGC_LIVE_STATUS, getContext().getString(R.string.player_status_leave));
                    }
                    break;
                case IVideoStatus.MEDIA_STATUS_END:
                    //直播结束
                    if (!isStatusEnd) {
                        canPlay = false;
                        isPlay = false;
                        isStatusEnd = true;
                        binding.videoView.release();
                        binding.infoView.show(PlayerInfoView.SHOW_UGC_LIVE_STATUS, getContext().getString(R.string.player_status_end));
                    }
                    break;
            }

        }

        @Override
        public void onError(int what, String extra) {
            Log.e("ugcLive status", "onError: " + extra);
        }
    };

    //播放器播放状态监听
    public interface OnVideoViewPlayStatusListener {
        void onVideoViewPlayStatus(boolean isPlay);
    }

    //ugc live 监听直播状态得需要android.permission.READ_PHONE_STATE
    public interface OnUgcLiveStatusPermissionListener {
        void onShouldRequestPermission();
    }
}