Управление медиа через MediaSession

1. Введение

Последнее обновление: 09.09.2020

В чём преимущества добавления MediaSession к воспроизведению видео?

Медиасессии являются неотъемлемой частью взаимодействия платформы Android и медиаприложений. Они не только сообщают Android о том, что воспроизводится медиаконтент, чтобы платформа могла перенаправлять действия с медиафайлами в нужную сессию, но и информируют платформу о том, что именно воспроизводится и как этим можно управлять.

Предоставление доступа к MediaSession через ваше приложение имеет множество преимуществ, которые понравятся пользователям. Вот несколько отличных примеров.

Google Ассистент

Пользователи могут легко взаимодействовать с медиаконтентом в вашем приложении с помощью голосовых команд, таких как «Пауза», «Возобновить» и «Далее». Метаданные из ваших медиафайлов также могут быть использованы для получения информации о том, что воспроизводится в данный момент.

Android TV

При работе с большими экранами ваше приложение для Android TV может использовать обычные пульты дистанционного управления для пользователей телевизоров, поддерживающих HDMI-CEC. Команды, отдаваемые кнопками воспроизведения/паузы, остановки, следующего и предыдущего трека, передаются в ваше приложение.

Экранные элементы управления мультимедиа

Начиная с Android 4.0 (уровень API 14), система может получать доступ к состоянию воспроизведения и метаданным медиасессии. Эта функция позволяет отображать элементы управления воспроизведением и обложку на экране блокировки. Такое поведение зависит от версии Android.

Фоновые медиа

В любом из этих сценариев можно управлять воспроизведением мультимедиа, даже если приложение, воспроизводящее медиафайлы, работает в фоновом режиме.

Окружающие вычисления

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

Что вы построите

В этом практическом задании вы расширите существующий пример Exoplayer, добавив поддержку медиасессий. Ваше приложение будет:

  • Корректно отобразить активное состояние медиасессии.
  • Передача управления воспроизведением медиафайлов на ExoPlayer
  • Передайте метаданные элементов в очереди в медиасессию.

Что вы узнаете

  • Почему медиасессии обеспечивают пользователям более насыщенный опыт
  • Как создать медиасессию и управлять её состоянием
  • Как подключить медиасессию к ExoPlayer
  • Как добавить метаданные элементов в очередь воспроизведения в сеансе воспроизведения мультимедиа
  • Как добавить дополнительные (пользовательские) действия

Данный практический урок посвящен SDK MediaSession. Несущественные концепции и блоки кода, включая подробности реализации ExoPlayer, не рассматриваются, но предоставлены для простого копирования и вставки.

Что вам понадобится

  • Требуется последняя версия Android Studio (3.5 или более поздняя).
  • Базовые знания в разработке приложений для Android.

2. Настройка

С чего мы начнём?

Начнём с основной демоверсии ExoPlayer. Эта демоверсия содержит видеоролики с экранными элементами управления воспроизведением, но не использует медиасессии по умолчанию. Это отличное место, чтобы начать работу и добавить их!

Получите образец ExoPlayer.

Для начала давайте рассмотрим пример ExoPlayer. Клонируйте репозиторий GitHub, запустив приведенный ниже код.

git clone https://github.com/google/ExoPlayer.git

Откройте демоверсию

В Android Studio откройте основной демонстрационный проект, расположенный в папке demos/main .

Android Studio предложит вам указать путь к SDK. Если у вас возникнут какие-либо проблемы, вы можете следовать рекомендациям по обновлению IDE и инструментов SDK .

10e3b5c652186d57.png

Если вас попросят использовать последнюю версию Gradle, смело обновляйте её.

Уделите немного времени, чтобы получить базовое представление о том, как устроено приложение. Обратите внимание, что здесь есть два класса Activity: SampleChooserActivity и PlayerActivity. Оставшуюся часть практического занятия мы проведем в классе PlayerActivity, где фактически воспроизводится медиаконтент, поэтому откройте этот класс и переходите к следующему разделу.

3. Создайте медиасессию и управляйте её состоянием.

Создать медиасессию

Откройте PlayerActivity.java . Этот класс создает ExoPlayer и управляет его функциями, такими как вывод видео на экран. В этой активности мы подключим ExoPlayer к медиасессии.

В верхней части класса объявите следующие два поля. Мы будем использовать эти поля на протяжении всего этого раздела.

private MediaSessionCompat mediaSession;
private MediaSessionConnector mediaSessionConnector;

Вам потребуется добавить зависимость проекта "extension-mediasession" в файл build.gradle на уровне модуля для параметра "Module: demo":

implementation project(path: ':extension-mediasession')

Обратите внимание, что Android Studio может помочь вам автоматически добавить эту зависимость, если вы наведете курсор мыши на ошибку при разрешении MediaSessionConnector:

60055e4ad54fbb97.png

Наконец, устраните проблемы с импортом классов, добавив следующее:

import android.support.v4.media.session.MediaSessionCompat;
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector;

При создании активности нам потребуется создать медиасессию и коннектор медиасессии, который будет служить посредником между медиасессией и ExoPlayer.

Идеальное место для вставки этого кода — там, где создается ExoPlayer. В нашем демонстрационном приложении мы можем добавить наш код в конец initializePlayer() . Обязательно добавьте эту логику после создания экземпляра плеера!

private void initializePlayer() {
  if (player == null) {
    ...
    player = ...
    ...
    mediaSession = new MediaSessionCompat(this, "sample");
    mediaSessionConnector = new MediaSessionConnector(mediaSession);
    mediaSessionConnector.setPlayer(player);
  }
  ...
}

Опубликовать пресс-конференцию

Освободите медиасессию, когда она больше не нужна. При освобождении ExoPlayer в releasePlayer() мы также можем добавить следующий код для этого:

private void releasePlayer() {
  if (mediaSession != null) {
    mediaSession.release();
  }
  ...
}

Управление состоянием медиа-сессии

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

Когда пользователь запускает действие, медиасессия должна стать активной:

@Override
public void onStart() {
  ...
  if (mediaSession != null) {
    mediaSession.setActive(true);
  }
}

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

@Override
public void onStop() {
  super.onStop();
  if (mediaSession != null) {
    mediaSession.setActive(false);
  }
  ...
}

Давайте запустим демоверсию.

  1. Подключите устройство Android или запустите эмулятор.
  2. Убедитесь, что для запуска из панели инструментов Android Studio выбран пункт "Демо". cb1ec4e50886874f.png
  3. Нажмите 9d8fb3a9ddf12827.png с панели инструментов Android Studio.
  4. После запуска приложения на вашем устройстве выберите видеопоток для воспроизведения.
  5. После начала воспроизведения попробуйте использовать следующие команды adb для управления медиасессией:
adb shell media dispatch pause
adb shell media dispatch play
adb shell media dispatch play-pause
adb shell media dispatch fast-forward
adb shell media dispatch rewind
  1. Также изучите, как Android видит вашу медиасессию. В частности, вы можете проверить, какие действия поддерживаются, посмотрев на поле action. Число, которое вы видите здесь, представляет собой комбинацию идентификаторов действий, объявленных в объекте PlaybackState . Чтобы просмотреть медиасессию, выполните команду: adb shell dumpsys media_session
  2. Если вы используете физическое устройство с микрофоном, попробуйте вызвать Google Ассистента и отдать голосовые команды, например: «Пауза», «Возобновить», «Перемотать на 1 минуту вперед».

b8dda02a6fb0f6a4.png Пример работы ExoPlayer на Android TV.

4. Включение метаданных элементов в очередь воспроизведения.

Теперь мы можем расширить поддерживаемые функции нашей медиасессии, где ранее мы создали MediaSessionConnector в initializePlayer() .

Добавление TimelineQueueNavigator

ExoPlayer представляет структуру медиафайлов в виде временной шкалы. Для получения подробной информации о том, как это работает, ознакомьтесь с объектом Timeline в ExoPlayer. Используя эту структуру, мы можем получать уведомления об изменениях контента и предоставлять метаданные о текущем воспроизведении по запросу.

Для этого мы определим TimelineQueueNavigator. Найдите экземпляр MediaSessionConnector в initializePlayer() и добавьте реализацию TimelineQueueNavigator после инициализации mediaSession .

mediaSessionConnector.setQueueNavigator(new TimelineQueueNavigator(mediaSession) {
  @Override
  public MediaDescriptionCompat getMediaDescription(Player player, int windowIndex) {
    return new MediaDescriptionCompat.Builder()
            .setTitle(player.getCurrentMediaItem().mediaMetadata.title)
            .setDescription("MediaDescription description for " + windowIndex)
            .setSubtitle("MediaDescription subtitle")
            .build();
  }
});

Устраните проблемы с импортом классов, добавив следующее:

import android.support.v4.media.MediaDescriptionCompat;
import com.google.android.exoplayer2.ext.mediasession.TimelineQueueNavigator;

Обратите внимание, что параметр windowIndex соответствует элементу с этим индексом в очереди воспроизведения.

Теперь, когда вы добавили метаданные, вы можете проверить, понимает ли Ассистент, что воспроизводится. Во время воспроизведения видео на Android TV вызовите Ассистента и спросите: «Что воспроизводится?»

6c7fc0cb853cbc38.png

5. Настройка действий

Возможно, ваш плеер не поддерживает некоторые действия, или вы хотели бы добавить поддержку большего количества? Давайте теперь немного углубимся в медиасессию, где мы ранее создали наш MediaSessionConnector в initializePlayer() .

Объявление о поддерживаемых действиях

Попробуйте использовать mediaSessionConnector.setEnabledPlaybackActions() чтобы настроить, какие действия должна поддерживать медиасессия.

Обратите внимание, что полный набор выглядит следующим образом:

mediaSessionConnector.setEnabledPlaybackActions(
        PlaybackStateCompat.ACTION_PLAY_PAUSE
                | PlaybackStateCompat.ACTION_PLAY
                | PlaybackStateCompat.ACTION_PAUSE
                | PlaybackStateCompat.ACTION_SEEK_TO
                | PlaybackStateCompat.ACTION_FAST_FORWARD
                | PlaybackStateCompat.ACTION_REWIND
                | PlaybackStateCompat.ACTION_STOP
                | PlaybackStateCompat.ACTION_SET_REPEAT_MODE
                | PlaybackStateCompat.ACTION_SET_SHUFFLE_MODE
);

Давайте еще раз посмотрим, как эти данные попадают на платформу:

  1. Как и прежде, запустите видео.
  2. Узнайте, как Android воспринимает метаданные вашей медиасессии, выполнив команду: adb shell dumpsys media_session
  3. Найдите строку, содержащую метаданные, и обратите внимание, что заголовок и описание включены и связаны с com.google.android.exoplayer2.demo/sample .

Добавление дополнительных действий

Мы можем расширить нашу сессию работы с медиафайлами, добавив несколько дополнительных действий. В этом разделе мы добавим только поддержку субтитров.

Вспомогательные подписи

Добавление поддержки субтитров к медиасессиям позволяет пользователям переключать их голосом. В том месте, где вы инициализировали коннектор медиасессий, добавьте следующее:

mediaSessionConnector.setCaptionCallback(new MediaSessionConnector.CaptionCallback() {
      @Override
      public void onSetCaptioningEnabled(Player player, boolean enabled) {
        Log.d("MediaSession", "onSetCaptioningEnabled: enabled=" + enabled);
      }

      @Override
      public boolean hasCaptions(Player player) {
        return true;
      }

      @Override
      public boolean onCommand(Player player, ControlDispatcher controlDispatcher, String command, Bundle extras, ResultReceiver cb) {
        return false;
      }
    }
);

Наконец, устраните все недостающие импорты.

Вы можете проверить это, вызвав Google Ассистента на Android TV и сказав «Включить субтитры». Проверьте Logcat, чтобы увидеть сообщения, которые вызывают ваш код.

6. Поздравляем!

Поздравляем, вы успешно добавили медиасессии в пример!

Вы получили огромный функционал благодаря:

  • добавление медиасессии,
  • подключение медиасессий к экземпляру ExoPlayer.
  • добавление метаданных и дополнительных действий.

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

В заключение

Данный практический пример построен на основе образца из исходного кода ExoPlayer. Нет необходимости использовать ExoPlayer из исходного кода, и рекомендуется вместо этого загрузить зависимости для ExoPlayer и MediaSessionConnector, чтобы было проще оставаться в курсе последних релизов.

Для этого достаточно заменить зависимости проекта следующим образом:

implementation project(modulePrefix + 'library-core')
implementation project(path: ':extension-mediasession')

для получения данных из репозиториев Maven, таких как:

implementation 'com.google.android.exoplayer:exoplayer-core:2.+'
implementation 'com.google.android.exoplayer:extension-mediasession:2.+'

Справочная документация