VideoView
资源
- Android三种播放视频的方式
- Android播放器框架分析之AwesomePlayer
- 音频与视频播放 讲的player类,比较全
视频播放原理:
系统会首先确定视频的格式,然后得到视频的编码..然后对编码进行解码,得到一帧一帧的图像,最后在画布上进行迅速更新,显然需要在独立的线程中完成,这时就需要使用surfaceView了
基本使用
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;
}
*/
错误信息
//常见错误: "无法播放此视频" -我测试的是:红米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(<