VR视频的具体实现步骤:
1.0 搭建VR开发环境,添加资源,修改Gradle,清单文件等
2.0 完成项目XML布局
3.0 自定义AsyncTask,读取显示VR视频
4.0 对VR消耗资源进行优化
5.0 显示视频播放进度及用户交互的操作
具体如下:
1.0 搭建VR开发环境,添加资源,修改Gradle,清单文件等
在main文件新建一个assets 文件 存放VR视频
在清单文件下 添加一行代码,降低警报权限,从192调高到512
android:largeHeap="true"
具体在哪里加,请参考上一篇 VR之全景图
导入库文件 common commonwidget 实现VR的基础 viedowidget(根据VR要实现的功能进行选择 该项目做的是VR视频 故要导入videowidget的库文件)
具体怎么添加库文件 关联库文件,请参考上一篇 VR之全景图
需要提醒的是 :
若和下面一致 库文件就配置成功了
修改自己新建的项目中的grandle 文件 与下面的文件修改成一致
添加此代码:compile 'com.google.android.exoplayer:exoplayer:r1.5.10'
compile 'com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-7'
2.0 完成项目XML布局
3.0 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.vrvideo.MainActivity">
<com.google.vr.sdk.widgets.video.VrVideoView
android:id="@+id/vr_video"
android:layout_width="match_parent"
android:layout_height="250dp">
</com.google.vr.sdk.widgets.video.VrVideoView>
<android.support.v7.widget.AppCompatSeekBar
android:id="@+id/seek_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_progress"
android:textSize="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
4.0 在MainActivity 中完成主要的代码
5.0 public class MainActivity extends AppCompatActivity {
private VrVideoView vrVideoView;
private SeekBar seekBar;
private TextView textView;
private VideoLoadTask videoLoadTask;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// A.初始化控件
vrVideoView = (VrVideoView) findViewById(R.id.vr_video);
seekBar = (SeekBar) findViewById(R.id.seek_bar);
textView = (TextView) findViewById(R.id.tv_progress);
//隐藏VR效果左下角的信息按钮显示
vrVideoView.setInfoButtonEnabled(false);
//切换VR模式 参数:
vrVideoView.setDisplayMode(VrVideoView.DisplayMode.FULLSCREEN_STEREO);
//对VR视频进行实践监听
vrVideoView.setEventListener(new MyEventListener());
//播放VR效果,只需要执行任务即可
videoLoadTask = new VideoLoadTask();
videoLoadTask.execute("congo_2048.mp4");
}
// B. 由于VR资源数据量很大,获取需要时间,故把加载视频放到子线程中进行,主线程来显示,可以使用异步任务AsyncTask或EVentbusjishu
// 自定义一个类继承自AsyncTask,只是用我们需要的方法,完成子线程加载图片资源,在主线程显示
private class VideoLoadTask extends AsyncTask<String,Void,Void>{
@Override
// B 该方法在子线程进行,从本地文件中把资源加载到内存中
protected Void doInBackground(String... params) {
//创建 VrVideoView.Options 对象,决定VR是普通模式,还是立体效果
VrVideoView.Options options = new VrVideoView.Options();
//立体模式
options.inputType=VrVideoView.Options.TYPE_STEREO_OVER_UNDER;
//处理加载的视频模式
//.FORMAT_HLS:流媒体数据格式(直播)
// .FORMAT_DEFAULT:默认模式(SD卡或assets)
options.inputFormat=VrVideoView.Options.FORMAT_DEFAULT;
try {
//提示:视频加载的方法还做了把视频读取到内存中的操作,所以它会有一个矛盾,调用该方法是在主线程还是在子线程(一般我们放在子线程去调用该方法)
// 使用VR控件对象,从资产目录加载视频资源,显示效果 参数 1.String对象 2. VrVideoView.Options对象,决定显示效果
vrVideoView.loadVideoFromAsset(params[0],options);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
//因为VR很占用内存,所以当界面进入OnPause状态,暂停VR视图显示,进入onResume状态啊,继续VR显示,进入onDestroy状态,杀死VR,
//当 我们失去焦点,回调
@Override
protected void onPause() {
super.onPause();
vrVideoView.pauseRendering();
}
@Override
protected void onResume() {
super.onResume();
vrVideoView.resumeRendering();
}
//当Activity 销毁时,回调
@Override
protected void onDestroy() {
super.onDestroy();
vrVideoView.shutdown();
//当退出activity 时,如果异步任务没有取消,则去取消
if (videoLoadTask !=null){
if(!videoLoadTask.isCancelled()){
videoLoadTask.cancel(true);
}
}
}
//对VR运行状态监听类,自定义一个继承类VrVideoEventListener,复写里面需要的方法
private class MyEventListener extends VrVideoEventListener{
//VR 视频加载成功的时候回调
public void onLoadSuccess(){
super.onLoadSuccess();
//获取视频长度
long max = vrVideoView.getDuration();
//设置SeekBar的进度最大值
seekBar.setMax((int)max);
}
//当视频加载失败时,回调
@Override
public void onLoadError(String errorMessage) {
super.onLoadError(errorMessage);
Toast.makeText(MainActivity.this,"加载失败",Toast.LENGTH_SHORT);
}
//当视频开始播放,每次进入下一帧的时候,回调这个方法(就是播放时,会不停的回调该方法)
@Override
public void onNewFrame() {
super.onNewFrame();
//获取当前视频的播放时间位置
int currentPosition = (int) vrVideoView.getCurrentPosition();
//设置seekBar的进度条
seekBar.setProgress(currentPosition);
//显示播放的进度数字
textView.setText("播放进度:" + String.format("%.2f",currentPosition/1000.f)+String.format("%.2f",vrVideoView.getCurrentPosition()/1000f));
}
//当视频播放结束后的回调
@Override
public void onCompletion() {
super.onCompletion();
//让视频回到0点
vrVideoView.seekTo(0);
//视频停止
vrVideoView.pauseVideo();
//让进度条也设置到0点
seekBar.setProgress(0);
//播放完成后,重新设置标签,标签true,暂停则播放
isPaused=true;
}
// 设置一个视频播放状态的标签
private boolean isPaused=false;
//重写点击视图的方法,使视频被点击时,播放或者暂停
@Override
public void onClick() {
super.onClick();
//根据标签,判断当前视频的状态,标签false ,播放则暂停,标签true,暂停则播放
if(isPaused){
vrVideoView.playVideo();
}else{
vrVideoView.pauseVideo();
}
//对标签操作一次后,进去取反
isPaused=!isPaused;
}
}
}