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
  • 1194

Android切换Fragment时视频依旧在播放,没有正常的停止。

最近开发Android应用,实现了用RadioGroup和ViewPager菜单导航栏的效果。但是在其中某个Fragment界面进行播放视频,切换到其他几个Fragment时,视频还在播放。 本以为在...
  • to_Baidu
  • to_Baidu
  • 2017年06月30日 23:42
  • 592

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

MediaPlayer类可用于控制播放音频/视频文件和流。关于如何使用这个类的方法的例子可以在VideoView找到。...
  • songshizhuyuan
  • songshizhuyuan
  • 2014年06月21日 19:32
  • 3322

View 生命周期方法

/**      * This is called when the view is attached to a window.  At this point it      * has a Su...
  • yuhailong626
  • yuhailong626
  • 2014年12月09日 15:05
  • 634

Android MediaPlayer和VideoView的使用

MediaPlayerMediaPlayer类是Androd多媒体框架中的一个重要组件,通过该类,我们可以以最小的步骤来获取,解码和播放音视频。它支持三种不同的媒体来源: 本地资源 内部URI,比如你...
  • huaxun66
  • huaxun66
  • 2016年11月25日 14:14
  • 16486

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

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

Android VideoView播放本地视频短暂黑屏的解决方法

新的大版本终于正式发布了,整整三个月,做的心力交瘁,导致好久都没有更新文章了。最近接触了许多新的知识,也算是忙碌中有所收获。希望接下来的时间工作上能够稍微松缓一些,让我可以利用在家的闲余时间把一些内容...
  • goodlixueyong
  • goodlixueyong
  • 2017年03月14日 21:34
  • 7783

Android 使用MediaPlayer播放视频切换后台暂停再恢复互前台继续播放的bug修改

import android.media.AudioManager; import android.media.MediaPlayer; import android.net.Uri; import ...
  • d06110902002
  • d06110902002
  • 2016年11月04日 13:54
  • 6650

Android 双屏异显

Android平板可以外接一块显示器,那么现在如果将VideoView显示在副屏(显示器)上,该如何实现呢?这里要用到Android的Presentation这个API:点击查看API详情我们现在新建...
  • wn1245343496
  • wn1245343496
  • 2017年09月17日 16:58
  • 374

Android MediaPlayer生命周期及状态说明

MediaPlayer的状态转换图也表征了它的生命周期,搞清楚这个图可以帮助我们在使用MediaPlayer时考虑情况更周全,写出的代码也更具健壮性。状态转换图清晰的描述了MediaPlayer的各个...
  • biaobiao1217
  • biaobiao1217
  • 2016年06月01日 17:56
  • 1353
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android VideoView 跟随Fragment生命周期切换视频播放,引起的ANR问题解答
举报原因:
原因补充:

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