Android VideoView 跟随Fragment生命周期切换视频播放,引起的ANR问题解答

原创 2017年01月03日 20:58:54

最近工作用遇到了需要根据当前所在fragment生命周期去控制全屏显示VideoView播放问题,但是由于MediaPlayer是基于状态机实现的,有一些操作,例如reset(),release()等等都是同步实现,所以频繁操作会引起ANR,解决方案就是将所用针对mediaPlayer的操作放到单独现场handler中去同一处理,达到同步处理的目的。

修改前代码如下:

@Override
    public void onResume() {
        super.onResume();
        isPause = false;
        if (canResume() && needResume && mVideoView != null) {
            sendStartVideoMsg();
            try {
                mVideoView.setVideoURI(Uri.parse("file://" + info.accUrl));
                mVideoView.start();
                needResume = false;
            } catch (Exception e) {

            }
        }
    }
    boolean isPause = false;
    @Override
    public void onPause() {
        super.onPause();
        isPause = true;
        if (mImageView != null && mImageView.getVisibility() != View.VISIBLE) {
            mImageView.setVisibility(View.VISIBLE);
        }
        if (canResume() && mVideoView != null) {
            if (mVideoView.isPlaying()) {
                mVideoView.stopPlayback();
            }
            needResume = true;
            onVideoStop(PreviewAccessoryType.TYPE_LOCAL_VIDEO, VIDEO_STOP);
        }
    }
修改后代码如下:

@Override
    public void onResume() {
        super.onResume();
        isPause = false;
        if (canResume() && needResume && mVideoView != null) {
            sendStartVideoMsg();
//            try {
//                mVideoView.setVideoURI(Uri.parse("file://" + info.accUrl));
//                mVideoView.start();
//                needResume = false;
//            } catch (Exception e) {
//
//            }
        }
    }
    boolean isPause = false;
    @Override
    public void onPause() {
        super.onPause();
        isPause = true;
        if (mImageView != null && mImageView.getVisibility() != View.VISIBLE) {
            mImageView.setVisibility(View.VISIBLE);
        }
        if (canResume() && mVideoView != null) {
            sendStopVideoMsg();
//            if (mVideoView.isPlaying()) {
//                mVideoView.stopPlayback();
//            }
            needResume = true;
            onVideoStop(PreviewAccessoryType.TYPE_LOCAL_VIDEO, VIDEO_STOP);
        }
    }

    private boolean canResume() {
        return mhidden == STATE_VISIBLE;
    }

    HandlerThread ht = new HandlerThread("stopPlayBack");
    Handler handler;

    private final int STOPPLAYBACK = 1000;
    private final int START = 2000;

    private void sendStartVideoMsg() {
        if (handler.hasMessages(STOPPLAYBACK)) {
            handler.removeMessages(STOPPLAYBACK);
        }
        if (handler.hasMessages(START)) {
            handler.removeMessages(START);
        }
        if (!handler.hasMessages(START)) {
            if (null != mVideoView) {
                try {
                    mVideoView.setVideoURI(Uri.parse("file://" + info.accUrl));
                } catch (Exception e) {
                }
                handler.sendEmptyMessage(START);
            }
        }
    }

    private void sendStopVideoMsg() {
        if (handler.hasMessages(START)) {
            handler.removeMessages(START);
        }
        if (handler.hasMessages(STOPPLAYBACK)) {
            handler.removeMessages(STOPPLAYBACK);
        }
        if (!handler.hasMessages(STOPPLAYBACK)) {
            if (null != mVideoView) {
                handler.sendEmptyMessage(STOPPLAYBACK);
            }
        }
    }

    private void startVideo() {
        if (mVideoView != null && !mVideoView.isPlaying()) {
            try {
                mVideoView.start();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void stopVideo() {
        if (mVideoView != null) {
            if (mVideoView.isPlaying()) {
                mVideoView.stopPlayback();
            }
            onVideoStop(PreviewAccessoryType.TYPE_LOCAL_VIDEO, VIDEO_STOP);
        }
    }

handler处理如下:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    initData(position, pos, info);
    ht.start();
    handler = new Handler(ht.getLooper()) {
        @Override
        public void handleMessage(Message msg) {
            try {
                switch (msg.what) {
                    case STOPPLAYBACK:
                        stopVideo();
                        break;
                    case START:
                        startVideo();
                        break;
                }
            } catch (Exception e) {

            }
            super.handleMessage(msg);
        }
    };
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

VideoView中的ANR

先看anr的打印native: #10 pc 0000050f /system/framework/x86/boot.oat (Java_android_media_MediaPlayer__1re...
  • iblade
  • iblade
  • 2016年11月28日 11:24
  • 946

Android关于VideoView的一些思考和总结

最近在做一期有关于视频的项目开发。因为项目周期比较紧,而且自己以前也没有对于视频相关的经验积累。所以在开发的时候遇到了问题,自己尝试解决并记录下来。(PS:视频都是下载完再进行播放类似于微信朋友圈的视...

MediaPlayer的生命周期以及状态转换

MediaPlayer类可用于控制播放音频/视频文件和流。关于如何使用这个类的方法的例子可以在VideoView找到。...

Android MediaPlayer 生命周期

MediaPlayer类可用于控制音频/视频文件或流的播放。关于如何使用这个类的方法还可以阅读VideoView类的文档。 1.状态图 对播放音频/视频文件和流的控制是通过一个状态机来管理...

Android中Fragment使用VideoView会出现只有声音没有图像的问题

1、初始化时,VideoView调用setBackgroundColor(颜色) 2、开始播放时,VideoView调用setBackgroundColor(0)...

VideoView的相关方法

public class VideoView extends SurfaceView implements MediaController.MediaPlayerControl  ...

Android 不得不说的VideoView的一些坑及其解决方案

Android 不得不说的VideoView的一些坑及其解决方案最近公司做动态展示新添加了视频,然后去摸索了一些视频的相关问题,最终选择了Android原生的VideoView。开发中遇到了一些坑给...

如何分析解决Android ANR

http://www.eoeandroid.com/forum.php?mod=viewthread&tid=165974 Log的产生大家都知道 , 大家也都知道通过DDMS来看log ,...

【乐视云学习笔记】关于Letv乐视云点播的视频暂停之后,按home回到桌面后重新onResume回到Activity,视频自动播放的情况

众所周知,乐视云是免费的,但是免费的东东呢,就是各式各样的问题啦,比如说文档写的不完善哇之类的,遇到问题求助,某度和gogo都无法搜出什么眉头来。只能求助于QQ 群里的乐视官方技术。有时候问一下也要过...

基于Android VideoView播放器的封装

一、绪 之前在群里看到有人在讨论Android VideoView的使用,发现大家都存在几个共同的问题。为了以后大家使用方便也为了自己使用方便,同样减少不必要的坑,便有了今天的内容,对Android...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android VideoView 跟随Fragment生命周期切换视频播放,引起的ANR问题解答
举报原因:
原因补充:

(最多只允许输入30个字)