创建一个Android Cardboard 360 Video Viewer

使用Google Cardboard拍摄海滩风景的图片

建立

在开始构建视频查看器应用程序之前,您将需要通过Git将Cardboard Android SDK克隆到计算机上。 您可以在本系列上一篇文章中找到有关此操作的说明。

对于我们的示例,使用最低API为19的SDK(KitKat)创建一个新的Android项目,并使用Empty Activity模板。

创建基础项目后,您将需要将Cardboard SDK的commoncommonwidgetvideowidget文件夹复制到项目的根目录。 将这些目录移走后,您需要通过编辑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'
}

您会注意到,我们添加了来自GoogleProtocol 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()方法的末尾分别将它们与VrVideoViewSeekBar关联。

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视频播放器

但是,如果旋转设备,则可能会注意到视频完全重新启动的不良行为。 我们可以通过使用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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值