Дополненная и виртуальная реальность, хотя и остается относительно новой, быстро стала популярной для приложений, в том числе для игр и образования. Ранее я показал вам, как установить Картон с помощью Android SDK и как создать панорамный просмотрщик изображений. Этот пост покажет вам, как использовать 360-градусное видео в ваших приложениях.
Настроить
Прежде чем вы начнете создавать приложение для просмотра видео, вам нужно будет клонировать 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-коду.
Работа с картоном и VR-видео
Прежде чем мы сможем начать писать весь код, который управляет состоянием воспроизведения, положением и загрузкой вашего видеофайла 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(); } | 
Теперь, когда начальная настройка нашего учебного класса завершена, мы можем перейти к более интересной теме: загрузка видео, управление воспроизведением и настройка пользовательского интерфейса.
  Запуск и управление VrVideoView 
  Поскольку загрузка видео 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, работающий в вашем приложении.

  Однако, если вы поворачиваете свое устройство, вы можете заметить, что нежелательное поведение видео полностью перезапускается.  Мы можем исправить это, работая с 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 и дополненной реальности!




