[Android基础] VideoView

本文详细介绍了Android中的VideoView组件,包括基本使用、全屏切换、获取第一帧作为封面、滑动控制亮度和音量,以及处理如进度跳动、暂停恢复时重新加载等常见问题。此外,还探讨了SurfaceView在黑屏问题上的解决方案,并提供了相关资源链接。
摘要由CSDN通过智能技术生成

Demo项目下载
自己封装了一个播放器

VideoView

资源

  1. Android三种播放视频的方式
  2. Android播放器框架分析之AwesomePlayer
  3. 音频与视频播放 讲的player类,比较全

视频播放原理:
系统会首先确定视频的格式,然后得到视频的编码..然后对编码进行解码,得到一帧一帧的图像,最后在画布上进行迅速更新,显然需要在独立的线程中完成,这时就需要使用surfaceView了

android 支持的编码格式

android_video_support_format

基本使用

VideoView mVv = (VideoView) findViewById(R.id.vv);
//添加播放控制条,还是自定义好点
mVv.setMediaController(new MediaController(this));

//设置视频源播放res/raw中的文件,文件名小写字母,格式: 3gp,mp4等,flv的不一定支持;
Uri rawUri = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.shuai_dan_ge);
mVv.setVideoURI(rawUri);

// 播放在线视频
mVideoUri = Uri.parse("http://****/abc.mp4");
mVv.setVideoPath(mVideoUri.toString());

mVv.start();
mVv.requestFocus();

/*
其他方法:
mVv.pause();
mVv.stop();
mVv.resume();
mVv.setOnPreparedListener(this);
mVv.setOnErrorListener(this);
mVv.setOnCompletionListener(this);**

Error信息处理 :
经常会碰到视频编码格式不支持的情况,这里还是处理一下,若不想弹出提示框就返回true;
http://developer.android.com/intl/zh-cn/reference/android/media/MediaPlayer.OnErrorListener.html

@Override 
public boolean onError(MediaPlayer mp, int what, int extra) { 
   if(what==MediaPlayer.MEDIA_ERROR_SERVER_DIED){ 
        Log.v(TAG,"Media Error,Server Died"+extra); 
   }else if(what==MediaPlayer.MEDIA_ERROR_UNKNOWN){ 
        Log.v(TAG,"Media Error,Error Unknown "+extra); 
   } 
return true; 
} 
*/

错误信息

QCMediaPlayer.java

//常见错误: "无法播放此视频" -我测试的是:红米1s电信版4.4.4无法播放,但在三星s6(5.1.1)上就可以播放
//播放源:http://27.152.191.198/c12.e.99.com/b/p/67/c4ff9f6535ac41a598bb05bf5b05b185/c4ff9f6535ac41a598bb05bf5b05b185.v.854.480.f4v
MediaPlayer-JNI: QCMediaPlayer mediaplayer NOT present
MediaPlayer: Unable to create media player
MediaPlayer: Couldn't open file on client side, trying server side
MediaPlayer: error (1, -2147483648)
MediaPlayer: Error (1,-2147483648)

有人说 用下面的方式可以处理该异常,但我是使用系统封装好的控件,这个操作不到吧? 先记录下:

MediaPlayer player = MediaPlayer.create(this, Uri.parse(sound_file_path));
MediaPlayer player = MediaPlayer.create(this, soundRedId, loop);

全屏播放 - 横竖屏切换

  • androidmanifest.xml 中依然还是定义竖屏,并定义一个切换横纵屏按钮 btnChange :
<activity
    android:name="lynxz.org.video.VideoActivity"
    android:configChanges="keyboard|orientation|screenSize"
    android:screenOrientation="portrait"
    android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
  • 布局:需要在 VidioView 外层套一个容器,比如:
    <RelativeLayout
        android:id="@+id/rl_vv"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:background="@android:color/black"
        android:minHeight="200dp"
        android:visibility="visible">

        <VideoView
            android:id="@+id/vv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"/>
    </RelativeLayout>

这么做是为了在切换屏幕方向的时候对 rl_vv 进行拉伸,而内部的 VideoView 会依据视频尺寸重新计算宽高,我们看看其 onMeasure() 源码就明了了,但若是直接具体指定了view的宽高,则视频会被拉伸:

//VideoView.java 
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int width = getDefaultSize(mVideoWidth, widthMeasureSpec);
    int height = getDefaultSize(mVideoHeight, heightMeasureSpec);
    ......
    setMeasuredDimension(width, height);
}
  • 按钮监听,手动切换
btnSwitch.setOnClickListener(View -> {
    if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    } else {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    }
});

设置VideoView布局尺寸

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    if (mVv == null) {
        return;
    }
    if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){
  //横屏
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        getWindow().getDecorView().invalidate();
        float height = DensityUtil.getWidthInPx(<
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值