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; } } }