Приложения, которые в настоящее время используют автономную библиотеку 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-интерфейсу проигрывателя через компоненты/процессы с помощью
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 и плагин Gradle для Android Studio до последней версии, которая работает с обновленными зависимостями, указанными выше. Например:
- Версия плагина Android Gradle: 7.1.0
- Версия Градла: 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» , затем «Создать» > «Очистить проект» , а затем «Создать» > «Перестроить проект» (отслеживайте свою сборку на вкладке «Сборка — вывод сборки»). Андроид студия .
Рекомендуемые последующие действия:
- Устраните ошибки, связанные с использованием нестабильных 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.5.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
.
Медиасессионконнектор | AndroidX Media3 |
---|---|
CustomActionProvider | MediaSession.Callback.onCustomCommand()/ MediaSession.setCustomLayout() |
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.5.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 . Части вашего кода, связанные с устаревшими классами, необходимо соответствующим образом изменить или вместо этого сопоставить с Media3MediaItem
.Общая модель асинхронного программирования изменилась на
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
в устаревшем мире, вы можете сделать то же самое, используя только MediaBrowser
в Media3.
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 безопасны в использовании, а ошибки lint являются побочным продуктом наших новых гарантий двоичной совместимости. Если вам не требуется строгая двоичная совместимость, эти ошибки можно безопасно подавить с помощью аннотации @OptIn
.
Фон
Ни ExoPlayer v1, ни v2 не давали строгих гарантий бинарной совместимости библиотеки между последующими версиями. Поверхность ExoPlayer API очень велика по своей конструкции, что позволяет приложениям настраивать практически каждый аспект воспроизведения. В последующих версиях ExoPlayer время от времени вносились переименования символов или другие критические изменения (например, новые обязательные методы в интерфейсах). В большинстве случаев эти поломки были устранены путем введения нового символа наряду с прекращением поддержки старого символа в нескольких версиях, чтобы дать разработчикам время на миграцию их использования, но это не всегда было возможно.
Эти критические изменения привели к двум проблемам для пользователей библиотек ExoPlayer v1 и v2:
- Обновление до версии ExoPlayer может привести к остановке компиляции кода.
- Приложение, которое зависело от ExoPlayer как напрямую, так и через промежуточную библиотеку, должно было гарантировать, что обе зависимости имеют одну и ту же версию, иначе двоичная несовместимость могла привести к сбоям во время выполнения.
Улучшения в Media3
Media3 гарантирует двоичную совместимость для части поверхности API. Части, которые не гарантируют двоичную совместимость, помечены @UnstableApi
. Чтобы прояснить это различие, использование нестабильных символов API генерирует ошибку ворса, если они не помечены @OptIn
.
После перехода с ExoPlayer v2 на Media3 вы можете увидеть множество нестабильных ошибок проверки API. Из-за этого может показаться, что Media3 «менее стабилен», чем ExoPlayer v2. Это не так. «Нестабильные» части API Media3 имеют тот же уровень стабильности, что и вся поверхность API ExoPlayer v2, а гарантии стабильной поверхности API Media3 вообще недоступны в ExoPlayer v2. Разница лишь в том, что ошибка ворса теперь предупреждает вас о различных уровнях стабильности.
Обработка нестабильных ошибок API
См . раздел устранения неполадок, посвященный этим ошибкам lint, для получения подробной информации о том, как аннотировать использование нестабильных API в Java и Kotlin с помощью @OptIn
.
Устаревшие API
Вы можете заметить, что вызовы устаревших API в Android Studio перечеркнуты. Мы рекомендуем заменить такие вызовы соответствующей альтернативой. Наведите указатель мыши на символ, чтобы просмотреть документ JavaDoc, в котором указано, какой API использовать вместо этого.
Примеры кода и демонстрационные приложения
- Демо-приложение сеанса AndroidX Media3 (мобильное устройство и WearOS)
- Пользовательские действия
- Уведомление системного интерфейса, MediaButton/BT
- Google Ассистент управления воспроизведением
- UAMP: Android Media Player (ветвь media3) (мобильный, AutomotiveOS)
- Уведомление системного интерфейса, MediaButton/BT, возобновление воспроизведения
- Управление воспроизведением Google Assistant/WearOS
- AutomotiveOS: пользовательская команда и вход в систему