Android模仿VideoView实现视频播放

Android模仿VideoView实现视频播放

  • VideoView介绍

  • 模仿VideoView实现步骤

  • 问题解决


快捷键

VideoView介绍

VideoView是android自带的原生视频空间,通过它,我们能够实现视频播放,进度控制等,不过也有一个通用的UI界面,有需求的话,那就必须进行自定义。

class VideoView extends SurfaceView implements MediaPlayerControl
videoView是通过继承SurfaceView并实现MediaPlayerControl,可以理解为自定义view,我这里是通过activity来实现的。
activity+surfaceview来实现视频功能

模仿VideoView实现步骤

1、使用surfaceview来承载视频播放界面—即布局文件中包含surfaceView
2、继承SurfaceHolder.Callback
3、在surfaceCreated方法回调中,指定mediaplay的display为surfaceview,当SurfaceView中的Surface被创建的时候被调用, 在这里我们指定MediaPlayer在当前的Surface中进行播放
4、对视频尺寸适配:可以实现MediaPlayer.OnPreparedListener,然后在onPrepared回调中进行尺寸适配
5、视频控制:通过实现MediaController.MediaPlayerControl来实现原生的视频控制,自定义的话,下文有提到
注意:本文只实现进度条是控制,没有添加手势控制。
第一二点基本不用解释,
第三点:在activity中,我们可以在oncreate或onPrepared方法中对mediaplay进行初始化,包括视频资源等(这里指的是本地文件),但是如果使用surfaceview作为视频播放的载体的话,需要在播放的时候,surfaceview实例化出来,所以需要在surfaceCreated中调用mPlayer.setDisplay(mSurface.getHolder());// 设置屏幕,避免出现空指针等问题,同时对于第五点,可以在此处进行attach controlView。
第四点:建议在onPrepared回调中实现,适配原理是视频的宽高和屏幕的宽高进行同比例缩放

@Override
    public void onPrepared(MediaPlayer mp) {
        //首先取得video的宽和高
        vWidth = mPlayer.getVideoWidth();
        vHeight = mPlayer.getVideoHeight();

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

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

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

            //设置surfaceView的布局参数
            mSurface.setLayoutParams(new LinearLayout.LayoutParams(vWidth, vHeight));
        }
        mPlayer.start();
        //此处根据需求是否显示控制进度条,hide为隐藏
        if (mMediaController != null) {
            mMediaController.show();
        }
    }

第五点:视频控制:实现MediaController.MediaPlayerControl可以实现控制,但UI是共用的,不能满足需求,所以我的方法就是重写MediaController
先介绍下接口MediaPlayerControl

        //开始
        void    start();
        //暂停
        void    pause();
        //获取视频长度,ms
        int     getDuration();
        //当前播放位置 ms
        int     getCurrentPosition();
        //跳转到某个位置ms,当pos<0,pos=0
        void    seekTo(int pos);
        //是否播放
        boolean isPlaying();
        //得到缓冲的百分比 
        int     getBufferPercentage();
        //是否能暂停
        boolean canPause();
        //是否可以后退
        boolean canSeekBackward();
        //时候可以快进
        boolean canSeekForward();

在以上这些方法中,我们需要调用对应的mediaplay的方法来实现controlVIew和视频同步。
关于重写MediaController,不是继承关系,而是在sdk中找到对应的MediaController.java文件,放在项目中,或者打成jar包引用。
以上就是集成步骤

问题解决

有三个问题需要注意下:

1.重写MediaController会报错,提示不能生成window

import com.android.internal.policy.PhoneWindow;
mWindow = new PhoneWindow(mContext);

所以我们这里需要使用反射的方法进行获取window对象

String POLICYMANAGER_CLASS_NAME = "com.android.internal.policy.PolicyManager";
       try {
           Class policyClass;
           policyClass = Class.forName(POLICYMANAGER_CLASS_NAME);
           Method meths[] = policyClass.getMethods();
           Method makenewwindow = null;
           // Method makenewwindow = policyClass.getMethod("makeNewWindow");
           for (int i = 0; i < meths.length; i++) {
               if (meths[i].getName().endsWith("makeNewWindow"))
                   makenewwindow = meths[i];
           }
           mWindow = (Window) makenewwindow.invoke(null, mContext);
       } catch (Exception e) {
           e.printStackTrace();
       }

通过反射可以在android6.0以下的版本运行,但是6.0会报空指针,原因是在6.0中找不到com.android.internal.policy.PhoneWindow,所以需要分开处理:

if(Build.VERSION.SDK_INT == Build.VERSION_CODES.M){
            //M
            try {
                Class windowClass = Class.forName("com.android.internal.policy.PhoneWindow");
                Constructor<?> localConstructor = windowClass.getConstructor(new Class[]{Context.class});
                mWindow = (Window) localConstructor.newInstance(new Object[]{BaseApplication.getContext()});//实例化Window,如果传的context不是Application的Context,就会奔溃
            }catch (Exception e) {
                e.printStackTrace();
            }
        }

2.手势控制:需要实现GestureDetector.OnGestureListener,需要注意的是在surfaceview的ontouch事件中使用 GestureDetector的替换

public boolean onTouch(View v, MotionEvent event)  
    {  
        // TODO Auto-generated method stub  
        return mGesture.onTouchEvent(event);  
    }  

以上就是全部内容,有兴趣的话,可以关注我的微信订阅号:
这里写图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android VideoView 是一个可以用来播放视频的视图控件,但是有时候会遇到无法播放某些视频的情况。 造成 Android VideoView 无法播放视频的原因有很多,下面是一些可能的原因: 1. 文件格式不受支持:Android VideoView支持播放视频格式有限,例如常见的MP4、3GP等格式,但是某些特殊格式如MKV、FLV等可能无法播放。 2. 编码方式不受支持:即使是支持的文件格式,如果视频使用了不受支持的编码方式,也无法播放Android支持的编码方式包括H.264、H.263等。 3. 视频文件损坏:如果视频文件本身损坏或者缺失必要的编码信息,也会导致无法播放。 4. 网络问题:如果播放视频来自网络,可能是网络连接问题导致无法播放。例如服务器问题、网络限速等。 解决这个问题的方法有几种: 1. 转码视频:将不受支持的视频格式或编码方式转换为支持的格式,可以使用一些视频转换工具来完成。 2. 使用其他视频播放器:如果VideoView无法播放某个视频,可以尝试其他的视频播放器,如ExoPlayer、VLC等。 3. 检查视频文件:确保视频文件没有损坏,尝试播放其他已知可以正常播放视频文件来检查。 4. 检查网络连接:如果视频来自网络,确保网络连接正常,并尝试使用其他网络或播放其他视频来排除网络问题。 总之,如果Android VideoView无法播放某个视频,我们需要先检查视频文件格式、编码方式、文件完整性以及网络连接等方面的问题,然后采取相应的解决方法来解决这个问题。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值