Приложения, которые в настоящее время используют автономную библиотеку com.google.android.exoplayer2 и androidx.media следует перенести на androidx.media3 . Используйте скрипт миграции для переноса файлов сборки Gradle, исходных файлов Java и Kotlin, а также файлов макета XML из ExoPlayer 2.19.1 в AndroidX Media3 1.1.1 .
Обзор
Перед миграцией ознакомьтесь со следующими разделами, чтобы узнать больше о преимуществах новых API, API для миграции и предварительных условиях, которым должен соответствовать проект вашего приложения.
Зачем переходить на Jetpack Media3
-  Это новый дом ExoPlayer , в то время как com.google.android.exoplayer2больше не поддерживается.
-  Доступ к API Player через компоненты/процессы осуществляется с помощью MediaBrowser/MediaController.
-  Используйте расширенные возможности API MediaSessionиMediaController.
- Рекламируйте возможности воспроизведения с детальным контролем доступа .
-  Упростите свое приложение , удалив MediaSessionConnectorиPlayerNotificationManager.
-  Обратная совместимость с клиентскими API, совместимыми с медиа ( MediaBrowserCompat/MediaControllerCompat/MediaMetadataCompat)
API-интерфейсы мультимедиа для миграции на AndroidX Media3
-  ExoPlayer и его расширения
 Это включает в себя все модули устаревшего проекта ExoPlayer, за исключением модуля mediasession , поддержка которого прекращена. Приложения или модули, зависящие от пакетов вcom.google.android.exoplayer2можно перенести с помощью скрипта миграции.
-  MediaSessionConnector (в зависимости от пакетов androidx.media.*androidx.media:media:1.4.3+)
 УдалитеMediaSessionConnectorи вместо него используйтеandroidx.media3.session.MediaSession.
-  MediaBrowserServiceCompat (в зависимости от пакетов androidx.media.*androidx.media:media:1.4.3+)
 Перенесите подклассыandroidx.media.MediaBrowserServiceCompatвandroidx.media3.session.MediaLibraryServiceи код, использующийMediaBrowserCompat.MediaItem, вandroidx.media3.common.MediaItem.
-  MediaBrowserCompat (в зависимости от пакетов android.support.v4.media.*androidx.media:media:1.4.3+)
 Перенесите клиентский код с помощьюMediaBrowserCompatилиMediaControllerCompatдля использованияandroidx.media3.session.MediaBrowserсandroidx.media3.common.MediaItem.
Предпосылки
- Убедитесь, что ваш проект находится под контролем исходного кода - Убедитесь, что вы можете легко отменить изменения, внесённые с помощью скриптовых инструментов миграции. Если ваш проект ещё не находится под контролем исходного кода, сейчас самое время начать это делать. Если по какой-то причине вы не хотите этого делать, создайте резервную копию проекта перед началом миграции. 
- Обновите ваше приложение - Мы рекомендуем обновить ваш проект, используя последнюю версию библиотеки ExoPlayer , и удалить все вызовы устаревших методов. Если вы планируете использовать скрипт для миграции, необходимо сопоставить версию, на которую вы обновляетесь, с версией, обрабатываемой скриптом. 
- Увеличьте compileSdkVersion вашего приложения как минимум до 32 . 
- Обновите Gradle и плагин Android Studio Gradle до последней версии, работающей с обновлёнными зависимостями, указанными выше. Например: - Версия плагина Android Gradle: 7.1.0
- Версия Gradle: 7.4
 
- Замените все подстановочные операторы импорта , которые используют звездочку (*), и используйте полностью квалифицированные операторы импорта: Удалите подстановочные операторы импорта и используйте Android Studio для импорта полностью квалифицированных операторов (F2 - Alt/Enter, F2 - Alt/Enter, ...). 
- Перейдите с - com.google.android.exoplayer2.PlayerViewна- com.google.android.exoplayer2.StyledPlayerView. Это необходимо, поскольку в AndroidX Media3 нет эквивалента- com.google.android.exoplayer2.PlayerView.
 
Миграция ExoPlayer с поддержкой скриптов
 Скрипт упрощает переход с com.google.android.exoplayer2 на новую структуру пакетов и модулей в androidx.media3 . Скрипт выполняет некоторые проверки валидации в вашем проекте и выводит предупреждения, если валидация не пройдена. В противном случае он применяет сопоставления переименованных классов и пакетов в ресурсах проекта Android Gradle, написанного на Java или Kotlin.
usage: ./media3-migration.sh [-p|-c|-d|-v]|[-m|-l [-x <path>] [-f] PROJECT_ROOT]
 PROJECT_ROOT: path to your project root (location of 'gradlew')
 -p: list package mappings and then exit
 -c: list class mappings (precedence over package mappings) and then exit
 -d: list dependency mappings and then exit
 -l: list files that will be considered for rewrite and then exit
 -x: exclude the path from the list of file to be changed: 'app/src/test'
 -m: migrate packages, classes and dependencies to AndroidX Media3
 -f: force the action even when validation fails
 -v: print the exoplayer2/media3 version strings of this script
 -h, --help: show this help text
Использование скрипта миграции
- Загрузите скрипт миграции из тега проекта ExoPlayer на GitHub, соответствующего версии, до которой вы обновили свое приложение: - curl -o media3-migration.sh \ "https://raw.githubusercontent.com/google/ExoPlayer/r2.19.1/media3-migration.sh"
- Сделайте скрипт исполняемым: - chmod 744 media3-migration.sh
- Запустите скрипт с - --helpчтобы узнать о параметрах.
- Запустите скрипт с - -l, чтобы вывести список файлов, выбранных для миграции (используйте- -f, чтобы принудительно вывести список без предупреждений):- ./media3-migration.sh -l -f /path/to/gradle/project/root
- Запустите скрипт с - -m, чтобы сопоставить пакеты, классы и модули с Media3. Запуск скрипта с опцией- -mприменит изменения к выбранным файлам.- Остановиться при ошибке проверки без внесения изменений
 - ./media3-migration.sh -m /path/to/gradle/project/root- Принудительная казнь
 - Если скрипт обнаружит нарушение предварительных условий, миграцию можно принудительно выполнить с помощью флага - -f:- ./media3-migration.sh -m -f /path/to/gradle/project/root
 # list files selected for migration when excluding paths
 ./media3-migration.sh -l -x "app/src/test/" -x "service/" /path/to/project/root
 # migrate the selected files
 ./media3-migration.sh -m -x "app/src/test/" -x "service/" /path/to/project/root
 Выполните эти шаги вручную после запуска скрипта с опцией -m :
-  Проверьте, как скрипт изменил ваш код : используйте инструмент сравнения и исправьте потенциальные проблемы (рассмотрите возможность отправки сообщения об ошибке , если вы считаете, что в скрипте есть общая проблема, которая была добавлена без передачи параметра -f).
-  Сборка проекта : используйте ./gradlew clean buildили в Android Studio выберите Файл > Синхронизировать проект с файлами Gradle , затем Сборка > Очистить проект , а затем Сборка > Пересобрать проект (отслеживайте сборку на вкладке «Сборка — Выходные данные сборки» в Android Studio) .
Рекомендуемые последующие шаги:
- Устранить ошибки, связанные с использованием нестабильных API .
- Замените устаревшие вызовы API : используйте предлагаемый API для замены. Наведите указатель мыши на предупреждение в Android Studio и обратитесь к документации JavaDoc по устаревшему символу, чтобы узнать, что использовать вместо данного вызова.
- Отсортируйте операторы импорта : откройте проект в Android Studio, затем щелкните правой кнопкой мыши узел папки пакета в средстве просмотра проекта и выберите «Оптимизировать импорт» для пакетов, содержащих измененные исходные файлы.
 Заменить MediaSessionConnector на androidx.media3.session.MediaSession
 В прежнем мире MediaSessionCompat MediaSessionConnector отвечал за синхронизацию состояния проигрывателя с состоянием сеанса и получение команд от контроллеров, требующих делегирования соответствующим методам проигрывателя. В AndroidX Media3 это делает MediaSession напрямую, без необходимости использования коннектора.
- Удалите все ссылки и использование MediaSessionConnector: если вы использовали автоматизированный скрипт для миграции классов и пакетов ExoPlayer, то, вероятно, скрипт оставил ваш код в некомпилируемом состоянии, связанном с - MediaSessionConnector, и эту ошибку невозможно исправить. Android Studio покажет вам неисправный код при попытке сборки или запуска приложения.
- В файле - build.gradle, в котором хранятся зависимости, добавьте зависимость реализации для модуля сеанса AndroidX Media3 и удалите устаревшую зависимость:- implementation "androidx.media3:media3-session:1.8.0"
- Замените - MediaSessionCompatна- androidx.media3.session.MediaSession.
- В коде, где вы создали устаревший - MediaSessionCompat, используйте- androidx.media3.session.MediaSession.Builderдля создания- MediaSession. Передайте плеер для создания конструктора сеансов.- val player = ExoPlayer.Builder(context).build() mediaSession = MediaSession.Builder(context, player) .setSessionCallback(MySessionCallback()) .build()
- Реализуйте - MySessionCallback, как того требует ваше приложение. Это необязательно. Если вы хотите разрешить контроллерам добавлять медиаэлементы в проигрыватель, реализуйте- MediaSession.Callback.onAddMediaItems(). Он обслуживает различные текущие и устаревшие методы API, добавляющие медиаэлементы в проигрыватель для воспроизведения с сохранением обратной совместимости. К ним относятся методы- MediaController.set/addMediaItems()контроллера Media3, а также методы- TransportControls.prepareFrom*/playFrom*устаревшего API. Пример реализации- onAddMediaItemsможно найти в- PlaybackServiceдемонстрационного приложения сеанса .
- Освободите медиа-сессию на участке кода, где вы удалили свою сессию перед миграцией: - mediaSession?.run { player.release() release() mediaSession = null }
 Функциональность MediaSessionConnector в Media3
 В следующей таблице показаны API-интерфейсы Media3, которые обрабатывают функциональные возможности, ранее реализованные в MediaSessionConnector .
| MediaSessionConnector | AndroidX Media3 | 
|---|---|
| CustomActionProvider | MediaSession.Callback.onCustomCommand()/ MediaSession.setMediaButtonPreferences() | 
| PlaybackPreparer | MediaSession.Callback.onAddMediaItems()(prepare()вызывается внутренне) | 
| QueueNavigator | ForwardingSimpleBasePlayer | 
| QueueEditor | MediaSession.Callback.onAddMediaItems() | 
| RatingCallback | MediaSession.Callback.onSetRating() | 
| PlayerNotificationManager | DefaultMediaNotificationProvider/ MediaNotification.Provider | 
Миграция MediaBrowserService в MediaLibraryService
 В AndroidX Media3 представлен MediaLibraryService , который заменяет MediaBrowserServiceCompat . Документация JavaDoc по MediaLibraryService и его суперклассу MediaSessionService служит хорошим введением в API и модель асинхронного программирования сервиса.
 MediaLibraryService обратно совместим с MediaBrowserService . Клиентское приложение, использующее MediaBrowserCompat или MediaControllerCompat , продолжает работать без изменения кода при подключении к MediaLibraryService . Для клиента не имеет значения, использует ли ваше приложение MediaLibraryService или устаревший MediaBrowserServiceCompat . 

- Для обеспечения обратной совместимости необходимо зарегистрировать оба интерфейса сервиса в файле - AndroidManifest.xml. Таким образом, клиент сможет найти ваш сервис по нужному интерфейсу:- <service android:name=".MusicService" android:exported="true"> <intent-filter> <action android:name="androidx.media3.session.MediaLibraryService"/> <action android:name="android.media.browse.MediaBrowserService" /> </intent-filter> </service>
- В файле - build.gradle, в котором хранятся зависимости, добавьте зависимость реализации для модуля сеанса AndroidX Media3 и удалите устаревшую зависимость:- implementation "androidx.media3:media3-session:1.8.0"
- Измените свой сервис так, чтобы он наследовался от - MediaLibraryServiceвместо- MediaBrowserService. Как уже говорилось,- MediaLibraryServiceсовместим с устаревшим- MediaBrowserService. Соответственно, более широкий API, предлагаемый сервисом клиентам, остаётся прежним. Поэтому приложение, вероятно, может сохранить большую часть логики, необходимой для реализации- MediaBrowserService, и адаптировать её для нового- MediaLibraryService.- Основные отличия от устаревшего - MediaBrowserServiceCompatзаключаются в следующем:- Реализуйте методы жизненного цикла сервиса: Методы, которые необходимо переопределить в самом сервисе, — это - onCreate/onDestroy, с помощью которых приложение выделяет/освобождает сеанс библиотеки, проигрыватель и другие ресурсы. Помимо стандартных методов жизненного цикла сервиса, приложению необходимо переопределить- onGetSession(MediaSession.ControllerInfo)для возврата- MediaLibrarySession, встроенного в- onCreate.
- Реализуйте MediaLibraryService.MediaLibrarySessionCallback: для создания сеанса требуется - MediaLibraryService.MediaLibrarySessionCallback, реализующий методы API домена. Таким образом, вместо переопределения методов API устаревшего сервиса вы переопределите методы- MediaLibrarySession.Callback.- Затем обратный вызов используется для создания - MediaLibrarySession:- mediaLibrarySession = MediaLibrarySession.Builder(this, player, MySessionCallback()) .build()- Полное описание API MediaLibrarySessionCallback можно найти в документации по API. 
- Реализуйте - MediaSession.Callback.onAddMediaItems(): Обратный вызов- onAddMediaItems(MediaSession, ControllerInfo, List<MediaItem>)обслуживает различные текущие и устаревшие методы API, которые добавляют медиаэлементы в проигрыватель для воспроизведения с сохранением обратной совместимости. К ним относятся методы- MediaController.set/addMediaItems()контроллера Media3, а также методы- TransportControls.prepareFrom*/playFrom*устаревшего API. Пример реализации обратного вызова можно найти в- PlaybackServiceдемонстрационного приложения сеанса .
- AndroidX Media3 использует - androidx.media3.common.MediaItemвместо MediaBrowserCompat.MediaItem и MediaMetadataCompat . Части кода, связанные с устаревшими классами, необходимо изменить соответствующим образом или сопоставить их с Media3- MediaItem.
- Общая модель асинхронного программирования была изменена на - Futuresв отличие от подхода с отсоединяемым- Resultв- MediaBrowserServiceCompat. Реализация вашей службы может возвращать асинхронный- ListenableFutureвместо отсоединения результата или немедленно возвращать Future для непосредственного возврата значения .
 
Удалить PlayerNotificationManager
 MediaLibraryService автоматически поддерживает уведомления мультимедиа , а PlayerNotificationManager можно удалить при использовании MediaLibraryService или MediaSessionService .
 Приложение может настроить уведомление , установив пользовательский MediaNotification.Provider в onCreate() , который заменит DefaultMediaNotificationProvider . Затем MediaLibraryService позаботится о запуске службы на переднем плане по мере необходимости.
 Переопределив MediaLibraryService.updateNotification() приложение может взять на себя полную ответственность за публикацию уведомлений и запуск/остановку службы на переднем плане по мере необходимости.
Перенос клиентского кода с помощью MediaBrowser
 В AndroidX Media3 MediaBrowser реализует интерфейсы MediaController/Player и может использоваться не только для просмотра медиабиблиотеки, но и для управления воспроизведением медиаконтента. Если в прежней версии приходилось создавать MediaBrowserCompat и MediaControllerCompat , то в Media3 можно сделать то же самое, используя только MediaBrowser .
 MediaBrowser можно создать и ожидать установления соединения со службой: 
scope.launch {
    val sessionToken =
        SessionToken(context, ComponentName(context, MusicService::class.java)
    browser =
        MediaBrowser.Builder(context, sessionToken))
            .setListener(BrowserListener())
            .buildAsync()
            .await()
    // Get the library root to start browsing the library.
    root = browser.getLibraryRoot(/* params= */ null).await();
    // Add a MediaController.Listener to listen to player state events.
    browser.addListener(playerListener)
    playerView.setPlayer(browser)
}
Ознакомьтесь с разделом Управление воспроизведением в медиасеансе, чтобы узнать, как создать MediaController для управления воспроизведением в фоновом режиме.
Дальнейшие шаги и очистка
Ошибки нестабильного API
 После перехода на Media3 вы можете столкнуться с ошибками линтинга, связанными с нестабильным использованием API. Эти API безопасны в использовании, а ошибки линтинга являются побочным продуктом наших новых гарантий двоичной совместимости. Если вам не требуется строгая двоичная совместимость, эти ошибки можно безопасно устранить с помощью аннотации @OptIn .
Фон
Ни ExoPlayer v1, ни ExoPlayer v2 не предоставляли строгих гарантий двоичной совместимости библиотеки между последующими версиями. API ExoPlayer изначально очень обширен, чтобы приложения могли настраивать практически каждый аспект воспроизведения. В последующих версиях ExoPlayer периодически вносились изменения в символы или другие критические изменения (например, новые обязательные методы в интерфейсах). В большинстве случаев эти проблемы решались путём введения нового символа и одновременного прекращения поддержки старого в нескольких версиях, что давало разработчикам время на миграцию своих практик, но это было возможно не всегда.
Эти критические изменения привели к двум проблемам для пользователей библиотек ExoPlayer v1 и v2:
- Обновление до версии ExoPlayer может привести к остановке компиляции кода.
- Приложение, которое зависело от ExoPlayer как напрямую, так и через промежуточную библиотеку, должно было гарантировать, что обе зависимости имеют одинаковую версию, в противном случае двоичная несовместимость могла привести к сбоям во время выполнения.
Улучшения в Media3
 Media3 гарантирует двоичную совместимость для части API. Части, не гарантирующие двоичную совместимость, отмечены аннотацией @UnstableApi . Чтобы подчеркнуть это различие, использование нестабильных символов API приводит к ошибке lint, если только они не аннотированы аннотацией @OptIn .
После миграции с ExoPlayer v2 на Media3 вы можете столкнуться с множеством ошибок линтинга нестабильного API. Из-за этого может показаться, что Media3 «менее стабилен», чем ExoPlayer v2. Это не так. «Нестабильные» части API Media3 имеют тот же уровень стабильности, что и весь API ExoPlayer v2, а гарантии стабильного API Media3 в ExoPlayer v2 вообще отсутствуют. Разница лишь в том, что ошибка линтинга теперь предупреждает о разных уровнях стабильности.
Обработка нестабильных ошибок API lint
 Подробную информацию о том, как аннотировать использование нестабильных API Java и Kotlin с помощью @OptIn , см. в разделе по устранению неполадок, связанных с этими ошибками lint.
Устаревшие API
Вы можете заметить, что вызовы устаревших API в Android Studio зачёркнуты. Мы рекомендуем заменить такие вызовы подходящими альтернативами. Наведите указатель мыши на символ, чтобы увидеть документацию JavaDoc с подсказками о том, какой API следует использовать.

Примеры кода и демонстрационные приложения
-  Демонстрационное приложение сессии AndroidX Media3 (мобильные устройства и WearOS)- Пользовательские действия
- Уведомление системного пользовательского интерфейса, MediaButton/BT
- Управление воспроизведением с помощью Google Assistant
 
-  UAMP: Android Media Player (ветка media3) (мобильные устройства, AutomotiveOS)- Уведомление системного пользовательского интерфейса, MediaButton/BT, возобновление воспроизведения
- Управление воспроизведением Google Assistant/WearOS
- AutomotiveOS: пользовательские команды и вход в систему
 
