Jetpack Media3 определяет интерфейс Player , описывающий базовые функции воспроизведения видео- и аудиофайлов. ExoPlayer — это реализация этого интерфейса по умолчанию в Media3. Мы рекомендуем использовать ExoPlayer, поскольку он предоставляет полный набор функций, охватывающих большинство сценариев воспроизведения, и может быть настроен для любых дополнительных вариантов использования. ExoPlayer также абстрагируется от фрагментации устройств и ОС, обеспечивая согласованную работу вашего кода во всей экосистеме Android. ExoPlayer включает в себя:
- Поддержка плейлистов
 - Поддержка различных прогрессивных и адаптивных форматов потоковой передачи
 - Поддержка вставки рекламы как на стороне клиента, так и на стороне сервера
 - Поддержка воспроизведения с защитой DRM
 
На этой странице вы найдете описание некоторых ключевых этапов создания приложения для воспроизведения, а более подробную информацию вы можете найти в наших полных руководствах по Media3 ExoPlayer .
Начиная
Для начала добавьте зависимость от модулей ExoPlayer, UI и Common Jetpack Media3:
implementation "androidx.media3:media3-exoplayer:1.8.0" implementation "androidx.media3:media3-ui:1.8.0" implementation "androidx.media3:media3-common:1.8.0"
 В зависимости от вашего варианта использования вам также могут понадобиться дополнительные модули от Media3, такие как exoplayer-dash для воспроизведения потоков в формате DASH.
 Обязательно замените 1.8.0 на предпочитаемую вами версию библиотеки. Актуальную версию можно найти в примечаниях к выпуску .
Создание медиаплеера
 С Media3 вы можете либо использовать включенную реализацию интерфейса Player , ExoPlayer , либо создать свою собственную реализацию.
Создание ExoPlayer
 Самый простой способ создания экземпляра ExoPlayer следующий: 
Котлин
val player = ExoPlayer.Builder(context).build()
Ява
ExoPlayer player = new ExoPlayer.Builder(context).build();
 Вы можете создать свой медиаплеер в методе жизненного цикла onCreate() Activity , Fragment или Service , где он находится.
 Builder включает ряд возможностей настройки, которые могут вас заинтересовать, например:
-  
setAudioAttributes()для настройки обработки аудиофокуса -  
setHandleAudioBecomingNoisy()для настройки поведения воспроизведения при отключении аудиовыходного устройства -  
setTrackSelector()для настройки выбора треков 
 Media3 предоставляет компонент пользовательского интерфейса PlayerView , который можно включить в файл макета вашего приложения. Этот компонент инкапсулирует PlayerControlView для управления воспроизведением, SubtitleView для отображения субтитров и Surface для рендеринга видео.
Подготовка игрока
 Добавьте медиафайлы в плейлист для воспроизведения с помощью методов setMediaItem() и addMediaItem() . Затем вызовите метод prepare() , чтобы начать загрузку медиафайлов и получить необходимые ресурсы.
 Эти действия не следует выполнять до тех пор, пока приложение не перейдёт на передний план. Если ваш проигрыватель находится в Activity или Fragment , это означает, что его подготовка выполняется в методе жизненного цикла onStart() на уровне API 24 и выше или в методе жизненного цикла onResume() на уровне API 23 и ниже. Для проигрывателя, находящегося в Service , его подготовка выполняется в onCreate() . Пример реализации методов жизненного цикла см. в практической работе по Exoplayer .
Управляйте игроком
После подготовки проигрывателя вы можете управлять воспроизведением, вызывая методы проигрывателя, такие как:
-  
play()иpause()для запуска и приостановки воспроизведения -  
seekTo()для поиска позиции в текущем медиа-элементе -  
seekToNextMediaItem()иseekToPreviousMediaItem()для навигации по плейлисту 
 Компоненты пользовательского интерфейса, такие как PlayerView или PlayerControlView будут обновляться соответствующим образом при привязке к проигрывателю.
Отпустите игрока
 Для воспроизведения могут потребоваться ресурсы, запас которых ограничен, например видеодекодеры, поэтому важно вызывать release() на проигрывателе, чтобы освободить ресурсы, когда проигрыватель больше не нужен.
 Если ваш проигрыватель находится в Activity или Fragment , освободите его в методе жизненного цикла onStop() на уровне API 24 и выше или в методе onPause() на уровне API 23 и ниже. Если проигрыватель находится в Service , его можно освободить в onDestroy() . Пример реализации методов жизненного цикла см. в практической работе по Exoplayer .
Управление воспроизведением с помощью медиа-сеанса
В Android медиа-сеансы предоставляют стандартизированный способ взаимодействия с медиаплеером через границы процессов. Подключение медиа-сеанса к плееру позволяет демонстрировать воспроизведение медиаконтента внешним пользователям и получать команды воспроизведения из внешних источников, например, для интеграции с системными элементами управления медиаконтентом на мобильных устройствах и устройствах с большим экраном.
Чтобы использовать медиа-сессии, добавьте зависимость от модуля Media3 Session:
implementation "androidx.media3:media3-session:1.8.0"
Создать медиа-сессию
 Вы можете создать MediaSession после инициализации проигрывателя следующим образом: 
Котлин
val player = ExoPlayer.Builder(context).build() val mediaSession = MediaSession.Builder(context, player).build()
Ява
ExoPlayer player = new ExoPlayer.Builder(context).build(); MediaSession mediaSession = new MediaSession.Builder(context, player).build();
 Media3 автоматически синхронизирует состояние Player с состоянием MediaSession . Это работает с любой реализацией Player , включая ExoPlayer , CastPlayer или пользовательскую реализацию.
Предоставить контроль другим клиентам
 Клиентские приложения могут реализовать медиаконтроллер для управления воспроизведением медиасеанса. Чтобы получать эти запросы, установите объект обратного вызова при создании MediaSession .
 Когда контроллер готовится подключиться к вашему медиасеансу, вызывается метод onConnect() . Вы можете использовать предоставленную ControllerInfo , чтобы решить, принять или отклонить запрос. См. пример в демонстрационном приложении Media3 Session .
 После подключения контроллер может отправлять команды воспроизведения в сеанс. Сеанс затем делегирует эти команды проигрывателю. Команды воспроизведения и плейлистов, заданные в интерфейсе Player автоматически обрабатываются сеансом.
 Другие методы обратного вызова позволяют обрабатывать, например, запросы на пользовательские команды воспроизведения и изменение списка воспроизведения . Эти методы обратного вызова также включают объект ControllerInfo , что позволяет контролировать доступ для каждого запроса отдельно.
Воспроизведение медиа в фоновом режиме
 Чтобы продолжить воспроизведение мультимедиа, когда приложение не находится на переднем плане, например, для воспроизведения музыки, аудиокниг или подкастов, даже если у пользователя закрыто приложение, ваш Player и MediaSession должны быть инкапсулированы в службу переднего плана . Media3 предоставляет для этой цели интерфейс MediaSessionService .
 Реализация MediaSessionService
 Создайте класс, расширяющий MediaSessionService , и создайте экземпляр MediaSession в методе жизненного цикла onCreate() . 
Котлин
class PlaybackService : MediaSessionService() { private var mediaSession: MediaSession? = null // Create your Player and MediaSession in the onCreate lifecycle event override fun onCreate() { super.onCreate() val player = ExoPlayer.Builder(this).build() mediaSession = MediaSession.Builder(this, player).build() } // Remember to release the player and media session in onDestroy override fun onDestroy() { mediaSession?.run { player.release() release() mediaSession = null } super.onDestroy() } }
Ява
public class PlaybackService extends MediaSessionService { private MediaSession mediaSession = null; @Override public void onCreate() { super.onCreate(); ExoPlayer player = new ExoPlayer.Builder(this).build(); mediaSession = new MediaSession.Builder(this, player).build(); } @Override public void onDestroy() { mediaSession.getPlayer().release(); mediaSession.release(); mediaSession = null; super.onDestroy(); } }
 В манифесте добавьте класс Service с фильтром намерений MediaSessionService и запросите разрешение FOREGROUND_SERVICE для запуска службы переднего плана:
<service
    android:name=".PlaybackService"
    android:foregroundServiceType="mediaPlayback"
    android:exported="true">
    <intent-filter>
        <action android:name="androidx.media3.session.MediaSessionService"/>
    </intent-filter>
</service>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
 Наконец, в созданном вами классе переопределите метод onGetSession() для управления доступом клиентов к вашему медиасеансу. Верните MediaSession для принятия запроса на подключение или null для его отклонения. 
Котлин
// This example always accepts the connection request override fun onGetSession( controllerInfo: MediaSession.ControllerInfo ): MediaSession? = mediaSession
Ява
@Override public MediaSession onGetSession(MediaSession.ControllerInfo controllerInfo) { // This example always accepts the connection request return mediaSession; }
Подключение к вашему пользовательскому интерфейсу
 Теперь, когда ваш медиасеанс находится в Service отдельном от Activity или Fragment , где находится пользовательский интерфейс вашего проигрывателя, вы можете использовать MediaController для их связи. В методе onStart() Activity или Fragment с вашим пользовательским интерфейсом создайте SessionToken для MediaSession , а затем используйте SessionToken для создания MediaController . Создание MediaController происходит асинхронно. 
Котлин
override fun onStart() { val sessionToken = SessionToken(this, ComponentName(this, PlaybackService::class.java)) val controllerFuture = MediaController.Builder(this, sessionToken).buildAsync() controllerFuture.addListener( { // Call controllerFuture.get() to retrieve the MediaController. // MediaController implements the Player interface, so it can be // attached to the PlayerView UI component. playerView.setPlayer(controllerFuture.get()) }, MoreExecutors.directExecutor() ) }
Ява
@Override public void onStart() { SessionToken sessionToken = new SessionToken(this, new ComponentName(this, PlaybackService.class)); ListenableFuture<MediaController> controllerFuture = new MediaController.Builder(this, sessionToken).buildAsync(); controllerFuture.addListener(() -> { // Call controllerFuture.get() to retrieve the MediaController. // MediaController implements the Player interface, so it can be // attached to the PlayerView UI component. playerView.setPlayer(controllerFuture.get()); }, MoreExecutors.directExecutor()) }
 MediaController реализует интерфейс Player , поэтому вы можете использовать те же методы, такие как play() и pause() для управления воспроизведением. Как и в случае с другими компонентами, не забывайте освобождать MediaController , когда он больше не нужен, например, с помощью метода жизненного цикла onStop() объекта Activity , вызвав MediaController.releaseFuture() .
Публикация уведомления
 Для публикации уведомлений в активном режиме требуются службы переднего плана. MediaSessionService автоматически создаст уведомление MediaStyle в виде объекта MediaNotification . Чтобы предоставить пользовательское уведомление, создайте MediaNotification.Provider с помощью DefaultMediaNotificationProvider.Builder или создайте собственную реализацию интерфейса поставщика. Добавьте поставщика в MediaSession с помощью setMediaNotificationProvider .
Реклама вашей библиотеки контента
 MediaLibraryService основан на MediaSessionService , позволяя клиентским приложениям просматривать медиаконтент, предоставляемый вашим приложением. Клиентские приложения реализуют MediaBrowser для взаимодействия с вашим MediaLibraryService .
 Реализация MediaLibraryService аналогична реализации MediaSessionService , за исключением того, что в onGetSession() необходимо возвращать MediaLibrarySession вместо MediaSession . В отличие от MediaSession.Callback , MediaLibrarySession.Callback включает дополнительные методы, позволяющие браузерному клиенту перемещаться по содержимому, предлагаемому вашей библиотечной службой.
 Аналогично MediaSessionService , объявите MediaLibraryService в манифесте и запросите разрешение FOREGROUND_SERVICE для запуска службы переднего плана: 
<service
    android:name=".PlaybackService"
    android:foregroundServiceType="mediaPlayback"
    android:exported="true">
    <intent-filter>
        <action android:name="androidx.media3.session.MediaLibraryService"/>
        <action android:name="android.media.browse.MediaBrowserService"/>
    </intent-filter>
</service>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
В примере выше включен фильтр намерений как для MediaLibraryService , так и, для обратной совместимости, для устаревшего MediaBrowserService . Дополнительный фильтр намерений позволяет клиентским приложениям, использующим API MediaBrowserCompat распознавать ваш Service .
 MediaLibrarySession позволяет обслуживать библиотеку контента в виде древовидной структуры с одним корневым элементом MediaItem . Каждый MediaItem в дереве может иметь любое количество дочерних элементов MediaItem . Вы можете обслуживать другой корень или другое дерево в зависимости от запроса клиентского приложения. Например, дерево, которое вы возвращаете клиенту, ищущему список рекомендуемых элементов мультимедиа, может содержать только корневой MediaItem и один уровень дочерних элементов MediaItem , тогда как дерево, возвращаемое другому клиентскому приложению, может представлять собой более полную библиотеку контента.
 Создание сеанса MediaLibrarySession
 MediaLibrarySession расширяет API MediaSession , добавляя API для просмотра контента. По сравнению с обратным вызовом MediaSession , обратный вызов MediaLibrarySession добавляет такие методы, как:
-  
onGetLibraryRoot()когда клиент запрашивает корневойMediaItemдерева контента -  
onGetChildren(), когда клиент запрашивает дочерние элементыMediaItemв дереве контента -  
onGetSearchResult()когда клиент запрашивает результаты поиска из дерева контента для заданного запроса 
 Соответствующие методы обратного вызова будут включать объект LibraryParams с дополнительными сигналами о типе дерева контента, который интересует клиентское приложение.