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

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

最近公司做动态展示新添加了视频,然后去摸索了一些视频的相关问题,最终选择了Android原生的VideoView。开发中遇到了一些坑给大家分享出来,不得不说很坑,希望给大家做视频播放做一个参考:先总结如下:

VideoView的问题及其解决方案:

1.视频播放时会有短暂的黑屏时间:
产生原因:视频文件加载到内存中是需要时间,这个时间可能导入VideoView全黑。

解决方法(1):给VideoView添加MediaPlayer.OnPreparedListener 监听事件,在其onPrepared(MediaPlayer mp) 方法回调中播放视频这个时候视频已经完成了加载。(PS:此方法在有些情况下使用有些问题,因为播放视频的时候MediaPlayer.OnPreparedListener 监听不到回调,要先用此方法解决最本质问题得好好研究一下源码)。
解决方法(2):笨方法,同时也是最直接的方法。在VideoView执行start() 方法时视频的预览图不是立即消失而是延迟几百毫秒之后消失,这是视频已经加载完成,当然体验上有些不好。

                        new Thread(new Runnable() {
                                @Override
                                public void run() {
                                    SystemClock.sleep(200);
                                    runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            //执行让预览图消失的方法
                                        }
                                    });

                                }
                            }).start();

2.进入有VideoView界面的Activity时会出现闪黑屏的情况(如论视频是否播放):

产生原因:不祥(本人认为好像是窗口的问题)

解决方法:在整个界面创建之前添加这行代码getWindow().setFormat(PixelFormat.TRANSLUCENT);
(PixelFormat.TRANSPARENT和PixelFormat.TRANSLUCENT作用差不多,都是使窗口支持透明度)

3.当前界面有视频播放时进入其他界面(或者谈起PopupWindow/分享到微信、朋朋友圈、QQ等),然后跳转回来后VideoView展示全黑(按home键再次进入app也会有同样的问题):

产生原因:VideoView被回收掉,而自己没做VideoView的状态保存处理

解决方法:在VideoView所在的Activity或者Fragment的生命周期中处理VideoView视频播放和暂停。(查看VideoView的生命周期)

4.在类似微信列表页视频播放点击大图播放时列表的VideoView回出现在大图的VideoView之上(PS:如果列表的VideoView和大图播放的VideoView不是同一个):
产生原因:SurfaceView默认会出现在最顶部的。
解决方法: 小图播放时要隐藏掉(GONE而不是INVISIBLE)。

5.VideoView嵌套ViewPager使用时,在滑动ViewPager过程中视VideoView会出现透明(此时VideoView是自动播放)(PS:此时Activity的主题为android:theme=”@style/Transparent”)。

产生原因:ViewPager在执行public void onPageSelected(int position) 方法时当前界面还是展示两个View。即下一个View并没有完全漏出来。

解决方法:定义ViewPager的ViewPager.OnPageChangeListener接口,覆盖public void onPageScrolled(int postion, float v, int i)方法,监听让下一个界面完全展现出来之后在执行public void onPageSelected(int position)方法。然后再在方法里处理下一个视频的播放以及上一个的停止。

6.使用VideoView造成界面其他组价焦点产生“遗失”:

现象:在ViewTreeObserver.addOnPreDrawListener添加新的OnPreDrawListener的onPreDraw多次执行。

解决办法(1):使用SurfaceView+MediaPlayer自定义播放器

解决办法(2):对VideoView的构造函数中的焦点处理的方法进行反处理,即在VideoView子类(这里应该就是自己写的自定义VideoView其继承SurfaceView)的构造方法中进行反处理。

自定义的VideoView 
public class VideoView extends SurfaceView
        implements MediaPlayerControl, SubtitleController.Anchor {
    private String TAG = "VideoView";
    /*其他代码省略*/
    //每个构造函数中都执行initVideoView
    public VideoView(Context context) {
        super(context);
        initVideoView();
    }
    public VideoView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
        initVideoView();
    }
    public VideoView(Context context, AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }
    public VideoView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        initVideoView();
    }
    /*其他代码省略*/
    private void initVideoView() {
        mVideoWidth = 0;
        mVideoHeight = 0;
        getHolder().addCallback(mSHCallback);
        getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        //start     下边3行代码是对焦点进行的处理,以及自己所谓的反处理
        setFocusable(true);  //子类setFocusable(false);
        setFocusableInTouchMode(true);   //子类setFocusableInTouchMode(false);
        requestFocus();   //子类clearFocus();
        //end
        mPendingSubtitleTracks = new Vector<Pair<InputStream, MediaFormat>>();
        mCurrentState = STATE_IDLE;
        mTargetState  = STATE_IDLE;
    }
    /*其他代码省略*/
 }

7.在VideoView的MediaPlayer.OnCompletionListener 回调监听public void onCompletion(MediaPlayer mp) 方法里进行视频的播放(PS:这个指的是视频的循环播放),在有些手机上不能正常重新播放。

产生原因:在部分手机上VideoView的MediaPlayer.OnCompletionListener 回调监听public void onCompletion(MediaPlayer mp) 方法里此时`VideoView.isPlaying() 的值还是为true。

解决办法:在VideoView的 MediaPlayer.OnCompletionListener 回调监听 public void onCompletion(MediaPlayer mp) 方法里对`VideoView.start() 方法进行延迟播放。一般这个时间不会太长,几百毫秒就可以。视觉感观上也还好。

8.手机分辨率导致的无法播放此视频的问题

产生原因:视频的分辨率与手机分辨率的问题

解决办法:设置surfaceView的布局参数

   //首先取得video的宽和高
                    int vWidth = player.getVideoWidth();
                    int vHeight = player.getVideoHeight();

                    if (vWidth > video_view.getWidth() || vHeight > video_view.getHeight()) {
                        //如果video的宽或者高超出了当前屏幕的大小,则要进行缩放
                        float wRatio = (float) vWidth / (float) video_view.getWidth();
                        float hRatio = (float) vHeight / (float) video_view.getHeight();

                        //选择大的一个进行缩放
                        float ratio = Math.max(wRatio, hRatio);

                        vWidth = (int) Math.ceil((float) vWidth / ratio);
                        vHeight = (int) Math.ceil((float) vHeight / ratio);

                        //设置surfaceView的布局参数
                        video_view.setLayoutParams(new LinearLayout.LayoutParams(vWidth, vHeight));

                        //然后开始播放视频

                        player.start();
                    }

这个写在setOnPreparedListener的onPrepared()方法中去执行

  • 12
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
Android中的VideoView是一个用于播放视频的视图控件,支持播放网络上的视频内容。RTSP(Real-Time Streaming Protocol)是一种实时流媒体传输协议,用于在网络上传输音视频数据。 要在Android中使用VideoView播放RTSP视频,需要进行以下步骤: 1. 在布局文件中添加VideoView控件: ``` <VideoView android:id="@+id/videoView" android:layout_width="match_parent" android:layout_height="wrap_content" /> ``` 2. 在Java代码中找到VideoView控件并设置其播放的视频路径: ``` VideoView videoView = findViewById(R.id.videoView); String videoUrl = "rtsp://example.com/video"; videoView.setVideoURI(Uri.parse(videoUrl)); ``` 3. 增加网络访问权限和音视频播放权限: ``` <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> ``` 4. 控制视频的播放和停止: ``` videoView.start(); // 开始播放 videoView.pause(); // 暂停播放 videoView.stopPlayback(); // 停止播放 ``` 需要注意的是,RTSP视频的播放可能受到网络速度和服务器支持等因素的影响,如果遇到播放问题,可以尝试改用其他播放方式或检查网络连接。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值