Использование медиа-сессии

Медиа-сеансы предоставляют универсальный способ взаимодействия с аудио- или видеоплеером. Сообщив Android о том, что в приложении воспроизводится медиафайл, приложению можно делегировать управление воспроизведением. Интеграция с сеансом мультимедиа позволяет приложению рекламировать воспроизведение мультимедиа извне и получать команды воспроизведения из внешних источников. Этими источниками могут быть физические кнопки (например, кнопка воспроизведения на гарнитуре или пульте дистанционного управления телевизора) или косвенные команды (например, команда «пауза» Google Assistant). Затем медиасеанс делегирует эти команды приложению, которое применяет их к медиаплееру, для которого становится прозрачным, откуда возникли команды.

Медиа-сессия живет вместе с игроком, которым она управляет. Вам следует создать и инициализировать медиа-сеанс в методе 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() . В следующем примере показано, как добавить элемент управления для действия «палец вверх».

Котлин

stateBuilder.addCustomAction(
        PlaybackStateCompat.CustomAction.Builder(
                CUSTOM_ACTION_THUMBS_UP,
                resources.getString(R.string.thumbs_up),
                thumbsUpIcon
        ).run {
            setExtras(customActionExtras)
            build()
        }
)

Ява

stateBuilder.addCustomAction(new PlaybackStateCompat.CustomAction.Builder(
    CUSTOM_ACTION_THUMBS_UP, resources.getString(R.string.thumbs_up), thumbsUpIcon)
    .setExtras(customActionExtras)
    .build());

Полный пример см. в универсальном музыкальном проигрывателе .

Вы отвечаете на действие с помощью onCustomAction() .

Котлин

override fun onCustomAction(action: String, extras: Bundle?) {
    when(action) {
        CUSTOM_ACTION_THUMBS_UP -> {
            ...
        }
    }
}

Ява

@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 в более ранних системах.

Помимо управления проигрывателем и управления переходами между состояниями мультимедийного сеанса, обратные вызовы также включают и отключают функции вашего приложения и контролируют его взаимодействие с другими приложениями и аппаратным обеспечением устройства. (См. Управление аудиовыходом ).

Реализация методов обратного вызова медиа-сессии зависит от структуры вашего приложения. См. отдельные страницы, описывающие, как использовать обратные вызовы в аудио- и видеоприложениях , и опишите, как следует реализовать обратные вызовы для каждого типа приложений.