Статьи

Создать Android Cardboard 360 Video Viewer

Дополненная и виртуальная реальность, хотя и остается относительно новой, быстро стала популярной для приложений, в том числе для игр и образования. Ранее я показал вам, как установить Картон с помощью Android SDK и как создать панорамный просмотрщик изображений. Этот пост покажет вам, как использовать 360-градусное видео в ваших приложениях.

  • Android SDK
    Начало работы с Android VR и Google Cardboard: панорамные изображения

Изображение сцены пляжа с Google Cardboard

Прежде чем вы начнете создавать приложение для просмотра видео, вам нужно будет клонировать Android Cardboard Android на ваш компьютер через Git. Вы можете найти инструкции для этого в предыдущей статье этой серии .

Для нашего примера создайте новый проект Android с минимальным SDK API 19 (KitKat) и используйте шаблон Empty Activity .

После создания базового проекта вам нужно будет скопировать папки common , commonwidget и videowidget из Cardboard SDK в корневой каталог вашего проекта. После того, как эти каталоги будут перемещены, вам нужно будет включить их как модули в ваш проект, отредактировав файл settings.gradle, чтобы он выглядел как следующий фрагмент.

1
include ‘:app’, «:common», «commonwidget», «videowidget»

Наконец, включите эти и другие необходимые библиотеки в свой проект, добавив следующие строки в файл build.gradle модуля приложения под узлом зависимостей .

01
02
03
04
05
06
07
08
09
10
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’
}

Вы заметите, что мы добавили библиотеку Protocol Buffers от Google , которая помогает управлять ресурсами времени выполнения на устройстве, и ExoPlayer , которая является созданной Google библиотекой VrVideoView которой построен компонент VrVideoView . Обе эти библиотеки требуются для работы Cardboard SDK, и вы, возможно, заметили, что используемая версия ExoPlayer относится к первой версии, а не ко второй, поэтому может вызывать конфликты, если вы используете ExoPlayer v2 в своих собственных проектах.

Затем мы хотим обновить наш файл activity_main.xml для нашего примера проекта, чтобы он включал VrVideoView , SeekBar и Button которой мы будем работать позже.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?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-коду.

Прежде чем мы сможем начать писать весь код, который управляет состоянием воспроизведения, положением и загрузкой вашего видеофайла 360, нам необходимо определить источник нашего видео. Для этого урока мы просто создадим папку ресурсов в главном каталоге и разместим там видео 360. Хотя есть несколько источников для 360 видео онлайн, я включил короткое общедоступное видео из Sea World, возвращающего морскую черепаху в океан, в сопровождающий проект GitHub для этого урока.

Теперь, когда у вас есть видеофайл для воспроизведения, откройте свой класс MainActivity .

Сначала вам нужно будет объявить и инициализировать элементы View , которые определены в файле макета, а также два boolean значения для отслеживания состояния приглушения и воспроизведения / паузы. Кроме того, мы OnClickListener на наш объект Button громкости.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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 . Этот класс будет иметь пять методов, которые мы можем реализовать для нашего простого средства просмотра видео.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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 в вашем классе и создать заглушки методов для этого интерфейса.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
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 , SeekBar их с вашими VrVideoView и SeekBar , соответственно, в конце метода initViews() который был определен выше.

1
2
mVrVideoView.setEventListener(new ActivityEventListener());
mSeekBar.setOnSeekBarChangeListener(this);

Есть еще один элемент настройки, о котором нужно позаботиться. Вам потребуется обработать жизненный цикл активности Android, поддерживая onPause() , onResume() и onDestroy() чтобы приостановить или возобновить рендеринг в VrVideoView или полностью его отключить. Вам также нужно будет отслеживать состояние паузы в этих методах.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
@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();
}

Теперь, когда начальная настройка нашего учебного класса завершена, мы можем перейти к более интересной теме: загрузка видео, управление воспроизведением и настройка пользовательского интерфейса.

Поскольку загрузка видео 360 может занять от доли секунды до нескольких секунд, вам нужно будет загрузить видео с помощью фоновой задачи. Давайте начнем с создания нового AsyncTask , который создаст новый объект VrVideoView.Options , установите тип ввода в соответствии с форматированием нашего видео (в случае с этим учебным TYPE_MONO , TYPE_MONO ), а затем загрузите наше видео из каталога активов .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
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 жизненного цикла AsyncTask .

1
2
VideoLoaderTask mBackgroundVideoLoaderTask = new VideoLoaderTask();
mBackgroundVideoLoaderTask.execute();

На этом этапе вы сможете запустить свое приложение и смотреть воспроизведение видео 360 в режиме просмотра видео с картона. Теперь, когда это работает, давайте добавим некоторую утилиту для нашего пользователя. Вернитесь к объекту ActivityEventListener который вы создали ранее в этом учебном пособии, так как мы захотим конкретизировать некоторые методы. Когда видео успешно загружено, нам нужно установить максимальное значение для нашего SeekBar , а также отслеживать состояние воспроизведения / паузы нашего видео.

1
2
3
4
5
6
7
@Override
public void onLoadSuccess() {
    super.onLoadSuccess();
 
    mSeekBar.setMax((int) mVrVideoView.getDuration());
    mIsPaused = false;
}

По мере воспроизведения видео мы будем обновлять этот SeekBar через onNewFrame() и возвращать видео в исходное положение в onCompletion() . Наконец, в onClick() мы запустим наш метод переключения воспроизведения / паузы.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
@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 . Мы можем сделать это с SeekBar.OnSeekBarChangeListener интерфейса SeekBar.OnSeekBarChangeListener который мы реализовали ранее.

1
2
3
4
5
6
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
    if( fromUser ) {
        mVrVideoView.seekTo(progress);
    }
}

Чтобы округлить наши VrVideoView управления VrVideoView , нам нужно реализовать методы переключения воспроизведения / паузы и громкости.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
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 .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
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);
}

Теперь, когда устройство повернуто, ваше видео должно вернуться в исходное положение, и ваш пользователь сможет продолжить работу в непрерывном режиме.

Несмотря на то, что для использования VrVideoView в Cardboard SDK необходимо обработать несколько мелких деталей, сложные компоненты, такие как фактическое воспроизведение и оптимизация, обрабатываются для вас компонентом, который легко реализовать.

Теперь вы сможете добавлять 360 видео в свои мультимедийные приложения, предоставляя своим пользователям интересную функцию, которая обогащает их опыт. В следующем уроке этой серии мы сосредоточимся на новом опыте Google VR под названием Daydream и на том, как использовать парный контроллер с вашими приложениями.

А пока посмотрите другие наши учебники по виртуальной реальности Android и дополненной реальности!

  • Android SDK
    Начало работы с Android VR и Google Cardboard: панорамные изображения
  • Мобильная разработка
    Покемон GO Стиль дополненной реальности с Vuforia
    Жестяная мегали
  • Мобильная разработка
    Создайте игру дополненной реальности Pokémon GO Style с Vuforia
    Жестяная мегали
  • Android
    Исследуйте VR с Google Картон
    Сью Смит