建立
在开始构建视频查看器应用程序之前,您将需要通过Git将Cardboard Android SDK克隆到计算机上。 您可以在本系列的上一篇文章中找到有关此操作的说明。
对于我们的示例,使用最低API为19的SDK(KitKat)创建一个新的Android项目,并使用Empty Activity模板。
创建基础项目后,您将需要将Cardboard SDK的common , commonwidget和videowidget文件夹复制到项目的根目录。 将这些目录移走后,您需要通过编辑settings.gradle文件使其看起来像下面的代码片段,将它们作为模块包含在项目中。
include ':app', ":common", "commonwidget", "videowidget"
最后,通过将以下行添加到依赖项节点下的应用程序模块的build.gradle文件中,将这些库和其他必需库包含在您的项目中。
dependencies {
compile 'com.android.support:appcompat-v7:25.0.0'
compile project(':common')
compile project(':commonwidget')
compile project(':videowidget')
compile 'com.google.android.exoplayer:exoplayer:r1.5.10'
compile 'com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-7'
}
您会注意到,我们添加了来自Google的Protocol Buffers库和ExoPlayer ,该库帮助管理设备上的运行时资源, ExoPlayer是由Google创建的VrVideoView
组件的基础视频播放器库。 这两个库都是Cardboard SDK必需的才能正常运行,并且您可能已经注意到,所使用的ExoPlayer版本来自第一个版本,而不是第二个版本,因此如果您在自己的项目中使用ExoPlayer v2,可能会导致冲突。
接下来,我们将为示例项目更新我们的activity_main.xml文件,以包括一个VrVideoView
,一个SeekBar
和一个Button
,稍后我们将使用它们。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.vr.sdk.widgets.video.VrVideoView
android:id="@+id/video_view"
android:layout_width="match_parent"
android:layout_height="250dp"/>
<SeekBar
android:id="@+id/seek_bar"
android:layout_height="32dp"
android:layout_width="match_parent"
style="?android:attr/progressBarStyleHorizontal"/>
<Button
android:id="@+id/btn_volume"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Volume Toggle"/>
</LinearLayout>
一旦完成了Cardboard库的设置并创建了我们将要使用的布局,就该跳入Java代码了。
使用Cardboard和VR视频
在我们开始编写用于控制360度视频文件中的播放状态,位置和加载的所有代码之前,我们需要确定视频的来源。 在本教程中,我们将只在主目录下创建一个asset文件夹,然后在其中放置360度视频。 尽管有一些在线360视频源,但在本教程随附的GitHub项目中,我包含了海洋世界的一段简短的公共视频,该视频将海龟送回了大海。
初始化和结构
现在您已经可以播放视频文件,打开MainActivity
类。
首先,您需要声明并初始化由布局文件定义的View
项,以及两个boolean
值以跟踪静音和播放/暂停状态。 另外,我们将在音量Button
对象上放置一个OnClickListener
。
public class MainActivity extends AppCompatActivity {
private VrVideoView mVrVideoView;
private SeekBar mSeekBar;
private Button mVolumeButton;
private boolean mIsPaused;
private boolean mIsMuted;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
}
private void initViews() {
mVrVideoView = (VrVideoView) findViewById(R.id.video_view);
mSeekBar = (SeekBar) findViewById(R.id.seek_bar);
mVolumeButton = (Button) findViewById(R.id.btn_volume);
mVolumeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onVolumeToggleClicked();
}
});
}
public void playPause() {
}
public void onVolumeToggleClicked() {
}
}
接下来,创建一个扩展VrVideoEventListener
的新内部类。 此类将提供五个方法,我们可以为简单的视频查看器实现这些方法。
private class ActivityEventListener extends VrVideoEventListener {
@Override
public void onLoadSuccess() {
super.onLoadSuccess();
}
@Override
public void onLoadError(String errorMessage) {
super.onLoadError(errorMessage);
}
@Override
public void onClick() {
super.onClick();
}
@Override
public void onNewFrame() {
super.onNewFrame();
}
@Override
public void onCompletion() {
super.onCompletion();
}
}
您还需要在您的类中实现SeekBar.OnSeekBarChangeListener
并为该接口创建方法存根。
public class MainActivity extends AppCompatActivity implements SeekBar.OnSeekBarChangeListener {
...
public void onPlayPausePressed() {
}
public void onVolumeToggleClicked() {
}
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
}
}
一旦创建了这个新的内部类和SeekBar
实现,请在上面定义的initViews()
方法的末尾分别将它们与VrVideoView
和SeekBar
关联。
mVrVideoView.setEventListener(new ActivityEventListener());
mSeekBar.setOnSeekBarChangeListener(this);
还有另外一个设置需要注意。 您将需要通过支持onPause()
, onResume()
和onDestroy()
方法来处理Android活动生命周期,以暂停或恢复VrVideoView
中的VrVideoView
或完全关闭它。 您还需要在这些方法中跟踪暂停状态。
@Override
protected void onPause() {
super.onPause();
mVrVideoView.pauseRendering();
mIsPaused = true;
}
@Override
protected void onResume() {
super.onResume();
mVrVideoView.resumeRendering();
mIsPaused = false;
}
@Override
protected void onDestroy() {
mVrVideoView.shutdown();
super.onDestroy();
}
现在,我们的教程课程的初始设置已经完成,我们可以进入一个更有趣的主题:加载视频,控制播放和自定义用户体验。
启动和控制VrVideoView
由于加载360度视频可能需要几秒钟到几秒钟的时间,因此您将需要通过后台任务来加载视频。 让我们首先创建一个新的AsyncTask
,它将创建一个新的VrVideoView.Options
对象,设置输入类型以匹配我们视频的格式(在本教程中为TYPE_MONO
),然后从资产目录中加载我们的视频。
class VideoLoaderTask extends AsyncTask<Void, Void, Boolean> {
@Override
protected Boolean doInBackground(Void... voids) {
try {
VrVideoView.Options options = new VrVideoView.Options();
options.inputType = VrVideoView.Options.TYPE_MONO;
mVrVideoView.loadVideoFromAsset("seaturtle.mp4", options);
} catch( IOException e ) {
//Handle exception
}
return true;
}
}
接下来,进入您的onCreate()
方法并创建此任务的新实例,然后调用execute()
启动它。 尽管需要做更多的工作来适当地维护此任务,但为简单起见,我们将在此方法中本地使用它,而不必担心AsyncTask
生命周期的注意事项。
VideoLoaderTask mBackgroundVideoLoaderTask = new VideoLoaderTask();
mBackgroundVideoLoaderTask.execute();
此时,您应该能够运行您的应用程序,并在Cardboard视频视图中观看360度视频播放。 现在工作正常了,让我们为用户添加一些实用程序。 返回到您在本教程前面创建的ActivityEventListener
对象,因为我们想充实一些方法。 视频成功加载后,我们需要为SeekBar
设置最大值,并跟踪视频的播放/暂停状态。
@Override
public void onLoadSuccess() {
super.onLoadSuccess();
mSeekBar.setMax((int) mVrVideoView.getDuration());
mIsPaused = false;
}
视频播放时,我们将通过onNewFrame()
更新SeekBar
,并将视频重置为onCompletion()
的初始位置。 最后,在onClick()
,我们将触发播放/暂停切换方法。
@Override
public void onClick() {
playPause();
}
@Override
public void onNewFrame() {
super.onNewFrame();
mSeekBar.setProgress((int) mVrVideoView.getCurrentPosition());
}
@Override
public void onCompletion() {
//Restart the video, allowing it to loop
mVrVideoView.seekTo(0);
}
尽管基于回放更新SeekBar
很重要,但我们也希望允许用户通过与SeekBar
进行交互来更改他们在视频中的位置。 我们可以使用我们之前实现的SeekBar.OnSeekBarChangeListener
接口来实现。
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if( fromUser ) {
mVrVideoView.seekTo(progress);
}
}
要完善我们的VrVideoView
控件,我们需要实现播放/暂停和音量切换方法。
public void playPause() {
if( mIsPaused ) {
mVrVideoView.playVideo();
} else {
mVrVideoView.pauseVideo();
}
mIsPaused = !mIsPaused;
}
public void onVolumeToggleClicked() {
mIsMuted = !mIsMuted;
mVrVideoView.setVolume(mIsMuted ? 0.0f : 1.0f);
}
此时,您应该在您的应用程序中具有一个可以正常工作的交互式360视频播放器。
![应用中显示的360视频播放器](https://i-blog.csdnimg.cn/blog_migrate/cd57dc0bd4b96b5ead858ae06122d182.png)
但是,如果旋转设备,则可能会注意到视频完全重新启动的不良行为。 我们可以通过使用Android的onSaveInstanceState()
和onRestoreInstanceState()
来保存和重置VrVideoView
的状态来VrVideoView
。
private static final String STATE_PROGRESS = "state_progress";
private static final String STATE_DURATION = "state_duration";
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putLong(STATE_PROGRESS, mVrVideoView.getCurrentPosition());
outState.putLong(STATE_DURATION, mVrVideoView.getDuration());
super.onSaveInstanceState(outState);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
long progress = savedInstanceState.getLong(STATE_PROGRESS);
mVrVideoView.seekTo(progress);
mSeekBar.setMax((int) savedInstanceState.getLong(STATE_DURATION));
mSeekBar.setProgress((int) progress);
}
现在,旋转设备后,您的视频应返回到其原始位置,并且用户可以继续获得不间断的体验。
结论
尽管要使用Cardboard SDK的VrVideoView需要处理一些小细节,但易于实现的组件可以为您处理一些困难的部分,例如实际播放和优化。
现在,您应该能够将360视频添加到媒体应用中,从而为用户提供有趣的功能,丰富他们的体验。 在本系列的下一个教程中,我们将重点介绍Google称为Daydream的新VR体验,以及如何在您的应用程序中使用配对控制器。
翻译自: https://code.tutsplus.com/tutorials/create-an-android-cardboard-360-video-viewer--cms-27689