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 .

Если вас попросят использовать последнюю версию 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:

Наконец, устраните проблемы с импортом классов, добавив следующее:
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);
}
...
}
Давайте запустим демоверсию.
- Подключите устройство Android или запустите эмулятор.
- Убедитесь, что для запуска из панели инструментов Android Studio выбран пункт "Демо".

- Нажмите
с панели инструментов Android Studio. - После запуска приложения на вашем устройстве выберите видеопоток для воспроизведения.
- После начала воспроизведения попробуйте использовать следующие команды
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
- Также изучите, как Android видит вашу медиасессию. В частности, вы можете проверить, какие действия поддерживаются, посмотрев на поле action. Число, которое вы видите здесь, представляет собой комбинацию идентификаторов действий, объявленных в объекте PlaybackState . Чтобы просмотреть медиасессию, выполните команду:
adb shell dumpsys media_session - Если вы используете физическое устройство с микрофоном, попробуйте вызвать Google Ассистента и отдать голосовые команды, например: «Пауза», «Возобновить», «Перемотать на 1 минуту вперед».
Пример работы 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 вызовите Ассистента и спросите: «Что воспроизводится?»

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
);
Давайте еще раз посмотрим, как эти данные попадают на платформу:
- Как и прежде, запустите видео.
- Узнайте, как Android воспринимает метаданные вашей медиасессии, выполнив команду:
adb shell dumpsys media_session - Найдите строку, содержащую метаданные, и обратите внимание, что заголовок и описание включены и связаны с
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.+'