Сеансы мультимедиа предоставляют универсальный способ взаимодействия с аудио- или видеопроигрывателем. Если сообщить Android, что в приложении воспроизводится медиаконтент, то элементы управления воспроизведением можно делегировать приложению. Интеграция с сеансом воспроизведения позволяет приложению сообщать о воспроизведении медиаконтента внешним источникам и получать от них команды воспроизведения. Это могут быть физические кнопки (например, кнопка воспроизведения на гарнитуре или пульте телевизора) или косвенные команды (например, "пауза" для Google Ассистента). Затем сеанс мультимедиа делегирует эти команды приложению, которое применяет их к медиапроигрывателю, для которого прозрачно, откуда поступили команды.
Сеанс мультимедиа существует вместе с проигрывателем, которым он управляет. Создавать и инициализировать сеанс воспроизведения медиаконтента следует в методе onCreate() действия или сервиса, которому принадлежит сеанс и связанный с ним проигрыватель.
Инициализация сеанса воспроизведения медиаконтента
У только что созданного сеанса воспроизведения нет возможностей. Чтобы инициализировать сеанс, выполните следующие действия:
- Установите флаги, чтобы сеанс мультимедиа мог получать обратные вызовы от контроллеров мультимедиа и кнопок мультимедиа.
- Создайте и инициализируйте экземпляр
PlaybackStateCompatи назначьте его сеансу. Состояние воспроизведения меняется в течение сеанса, поэтому рекомендуем кешироватьPlaybackStateCompat.Builderдля повторного использования. - Создайте экземпляр
MediaSessionCompat.Callbackи назначьте его сеансу (подробнее об обратных вызовах ниже).
Создавать и инициализировать медиасеанс следует в методе onCreate() активности или сервиса, которому принадлежит сеанс.
Чтобы кнопки управления медиаконтентом работали, когда приложение только инициализировано или остановлено, его объект PlaybackState должен содержать действие воспроизведения, соответствующее намерению, которое отправляет кнопка. Поэтому при инициализации состоянию сеанса присваивается значение ACTION_PLAY. Подробную информацию можно найти в статье Реагирование на кнопки мультимедиа.
Как поддерживать состояние воспроизведения и метаданные
Состояние медиасеанса представляют два класса.
Класс PlaybackStateCompat описывает текущее рабочее состояние проигрывателя. Примеры:
- Состояние транспорта (воспроизведение, пауза, буферизация и т. д.). См.
getState(). - Код ошибки и сообщение об ошибке (если применимо). (см.
getErrorCode()и Статусы и ошибки ниже). - Позиция игрока
- Допустимые действия контроллера, которые могут быть обработаны в текущем состоянии.
Класс MediaMetadataCompat описывает воспроизводимый материал:
- имя исполнителя, название альбома и трека;
- Продолжительность трека.
- Обложка альбома для показа на заблокированном экране. Изображение представляет собой растровое изображение с максимальным размером 320x320dp (если оно больше, оно уменьшается).
- Экземпляр
ContentUris, указывающий на увеличенную версию обложки.
Состояние проигрывателя и метаданные могут меняться в течение сеанса воспроизведения. Каждый раз, когда состояние или метаданные меняются, вы должны использовать соответствующий конструктор для каждого класса, PlaybackStateCompat.Builder() или MediaMetadataCompat.Builder(), а затем передать новый экземпляр в медиасеанс, вызвав setPlaybackState() или setMetaData().
Чтобы снизить общее потребление памяти при этих частых операциях, рекомендуется создать построители один раз и повторно использовать их на протяжении всего сеанса.
Статусы и ошибки
Обратите внимание, что PlaybackState – это объект, который содержит отдельные значения для состояния воспроизведения сеанса (getState()) и, при необходимости, связанный код ошибки (getErrorCode()). Ошибки могут быть критическими и некритическими.
Если воспроизведение прерывается, необходимо сгенерировать критическую ошибку: задать для состояния передачи значение STATE_ERROR и указать связанную ошибку с помощью setErrorMessage(int, CharSequence).
Пока воспроизведение заблокировано из-за ошибки, PlaybackState должен продолжать сообщать о STATE_ERROR и ошибке.
Некритическая ошибка возникает, когда приложение не может обработать запрос, но может продолжить воспроизведение.
Транспорт остается в нормальном состоянии (например, STATE_PLAYING), но PlaybackState содержит код ошибки.
Например, если пользователь хочет пропустить последний трек, воспроизведение может продолжиться, но вам нужно создать новый объект PlaybackState с кодом ошибки ERROR_CODE_END_OF_QUEUE и вызвать setPlaybackState(). Контроллеры мультимедиа, подключенные к сеансу, получат обратный вызов onPlaybackStateChanged() и объяснят пользователю, что произошло. О некритической ошибке нужно сообщать только один раз – когда она происходит. При следующем обновлении сеанса PlaybackState не должны снова устанавливать ту же некритическую ошибку (если только она не возникла в ответ на новый запрос).
Заблокированные экраны сеансов воспроизведения медиаконтента
Начиная с Android 4.0 (уровень API 14), система может получать доступ к состоянию воспроизведения и метаданным сеанса мультимедиа. Вот как на заблокированном экране могут выглядеть элементы управления мультимедиа и обложка. Поведение зависит от версии Android.
Обложки альбомов
В Android 4.0 (уровень API 14) – Android 10 (уровень API 29) на заблокированном экране показывается обложка альбома, но только если в метаданных сеанса воспроизведения есть фоновое растровое изображение.
Элементы управления воспроизведением
В Android 4.0 (API уровня 14) – Android 4.4 (API уровня 19), когда сеанс воспроизведения активен и его метаданные включают фоновое растровое изображение, на заблокированном экране автоматически появляются элементы управления.
В Android 5.0 (уровень API 21) и более поздних версиях на заблокированном экране нет элементов управления воспроизведением. Вместо этого для отображения элементов управления транспортом следует использовать уведомление MediaStyle.
Добавить настраиваемые действия
Мультимедийные приложения могут определять специальные действия, например "Нравится", "Лайк" или "Перемотать на 30 секунд назад". Настраиваемое действие должно реализовывать совершенно новое поведение. Не используйте настраиваемое действие вместо стандартных действий управления транспортом, определенных в PlaybackStateCompat.
Добавьте настраиваемые действия с помощью addCustomAction(). В примере ниже показано, как добавить элемент управления для действия "Нравится".
Kotlin
stateBuilder.addCustomAction( PlaybackStateCompat.CustomAction.Builder( CUSTOM_ACTION_THUMBS_UP, resources.getString(R.string.thumbs_up), thumbsUpIcon ).run { setExtras(customActionExtras) build() } )
Java
stateBuilder.addCustomAction(new PlaybackStateCompat.CustomAction.Builder( CUSTOM_ACTION_THUMBS_UP, resources.getString(R.string.thumbs_up), thumbsUpIcon) .setExtras(customActionExtras) .build());
Полный пример можно найти в Universal Music Player.
Вы отвечаете на действие с помощью onCustomAction().
Kotlin
override fun onCustomAction(action: String, extras: Bundle?) { when(action) { CUSTOM_ACTION_THUMBS_UP -> { ... } } }
Java
@Override public void onCustomAction(@NonNull String action, Bundle extras) { if (CUSTOM_ACTION_THUMBS_UP.equals(action)) { ... } }
Также ознакомьтесь с универсальным музыкальным проигрывателем.
Обратные вызовы мультимедийных сеансов
Основные методы обратного вызова сеанса мультимедиа: onPlay(), onPause() и onStop().
Здесь вы добавляете код, который управляет проигрывателем.
Поскольку вы создаете экземпляр и задаете обратный вызов сеанса во время выполнения (в onCreate()), ваше приложение может определять альтернативные обратные вызовы, которые используют разные проигрыватели, и выбирать подходящую комбинацию обратного вызова и проигрывателя в зависимости от устройства и/или уровня системы. Вы можете изменить проигрыватель, не меняя остальную часть приложения. Например, вы можете использовать ExoPlayer при работе на Android 4.1 (уровень API 16) или более поздней версии и использовать MediaPlayer в более ранних системах.
Помимо управления проигрывателем и переходами между состояниями сеанса, обратные вызовы также включают и отключают функции приложения и управляют его взаимодействием с другими приложениями и аппаратным обеспечением устройства. (см. раздел Управление выводом аудио).
Реализация методов обратного вызова сеанса мультимедиа зависит от структуры приложения. О том, как использовать обратные вызовы в аудиоприложениях и видеоприложениях, рассказывается в отдельных статьях.