現在スタンドアロンの 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は廃止されました。
- MediaBrowser/- MediaControllerを使用して、コンポーネント/プロセス全体で Player API にアクセス。
- MediaSessionAPI と- MediaControllerAPI の拡張機能を使用します。
- きめ細かいアクセス制御で再生機能をアドバタイズします。
- MediaSessionConnectorと- PlayerNotificationManagerを削除して、アプリを簡素化します。
- media-compat クライアント API(MediaBrowserCompat/MediaControllerCompat/MediaMetadataCompat)と後方互換性あり
AndroidX Media3 に移行するメディア API
- ExoPlayer とその拡張機能 
 これには、廃止された mediasession モジュールを除く、以前の ExoPlayer プロジェクトのすべてのモジュールが含まれます。com.google.android.exoplayer2のパッケージに依存するアプリやモジュールは、移行スクリプトで移行できます。
- MediaSessionConnector(androidx.media:media:1.4.3+のandroidx.media.*パッケージに依存)
 MediaSessionConnectorを削除し、代わりにandroidx.media3.session.MediaSessionを使用します。
- MediaBrowserServiceCompat(androidx.media:media:1.4.3+のandroidx.media.*パッケージによる)
 androidx.media.MediaBrowserServiceCompatのサブクラスをandroidx.media3.session.MediaLibraryServiceに、MediaBrowserCompat.MediaItemを使用するコードをandroidx.media3.common.MediaItemに移行します。
- MediaBrowserCompat(androidx.media:media:1.4.3+のandroid.support.v4.media.*パッケージに依存)
 MediaBrowserCompatまたはMediaControllerCompatを使用するクライアント コードを移行して、androidx.media3.common.MediaItemでandroidx.media3.session.MediaBrowserを使用するようにします。
前提条件
- プロジェクトがソース管理下にあることを確認する - スクリプト化された移行ツールによって適用された変更を簡単に元に戻せるようにします。プロジェクトをまだソース管理下に置いていない場合は、今が始める絶好の機会です。なんらかの理由で移行したくない場合は、移行を開始する前にプロジェクトのバックアップ コピーを作成してください。 
- アプリを更新する - プロジェクトをアップデートして、ExoPlayer ライブラリの最新バージョンを使用し、非推奨メソッドの呼び出しを削除することをおすすめします。移行にスクリプトを使用する場合は、更新するバージョンをスクリプトで処理されるバージョンと一致させる必要があります。 
- アプリの compileSdkVersion を 32 以上に引き上げます。 
- 上記の更新された依存関係で動作する最新バージョンに Gradle と Android Studio Gradle プラグインをアップグレードします。たとえば、次のようにします。 - Android Gradle プラグインのバージョン: 7.1.0
- Gradle のバージョン: 7.4
 
- アスタリスク(*)を使用しているすべてのワイルドカード import ステートメントを置き換えて、完全修飾 import ステートメントを使用します。ワイルドカード import ステートメントを削除し、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 の新しいパッケージとモジュール構造に簡単に移行できます。このスクリプトは、プロジェクトに対していくつかの検証チェックを行い、検証に失敗した場合は警告を出力します。それ以外の場合は、Java または Kotlin で記述された Android Gradle プロジェクトのリソースにある名前変更されたクラスとパッケージのマッピングを適用します。
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
移行スクリプトの使用
- アプリを更新したバージョンに対応する GitHub の ExoPlayer プロジェクトのタグから、移行スクリプトをダウンロードします。 - 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 で [File] > [Sync Project with Gradle Files] を選択し、[Build] > [Clean project]、[Build] > [Rebuild project] の順に選択します(Android Studio の [Build - Build Output] タブでビルドをモニタリングします)。
推奨されるフォローアップの手順:
- 不安定な API の使用に関するエラーのオプトインを解決します。
- 非推奨の API 呼び出しを置き換える: 推奨される代替 API を使用します。Android Studio で警告にポインタを合わせ、非推奨のシンボルの JavaDoc を参照して、特定の呼び出しの代わりに何を使用すべきかを確認します。
- インポート文を並べ替える: Android Studio でプロジェクトを開き、プロジェクト ビューアでパッケージ フォルダノードを右クリックして、変更されたソースファイルを含むパッケージで [Optimize imports] を選択します。
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 メソッドとレガシー API メソッドを提供します。これには、Media3 コントローラの- MediaController.set/addMediaItems()メソッドと、以前の API の- TransportControls.prepareFrom*/playFrom*メソッドが含まれます。- onAddMediaItemsの実装例は、セッション デモアプリの- PlaybackServiceにあります。
- 移行前にセッションを破棄したコードサイトでメディア セッションを解放します。 - mediaSession?.run { player.release() release() mediaSession = null }
Media3 の MediaSessionConnector 機能
次の表に、以前 MediaSessionConnector で実装されていた機能を処理する Media3 API を示します。
| 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 では、MediaBrowserServiceCompat に代わる MediaLibraryService が導入されています。MediaLibraryService とそのスーパークラス MediaSessionService の JavaDoc は、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"
- サービスを - MediaBrowserServiceではなく- MediaLibraryServiceから継承するように変更する 前述のとおり、- MediaLibraryServiceは以前の- MediaBrowserServiceと互換性があります。したがって、サービスがクライアントに提供するより広範な API は同じです。そのため、アプリは- MediaBrowserServiceを実装するために必要なロジックのほとんどを保持し、新しい- MediaLibraryServiceに適応させることができます。- 以前の - MediaBrowserServiceCompatとの主な違いは次のとおりです。- サービス ライフサイクル メソッドを実装する: サービス自体でオーバーライドする必要があるメソッドは - onCreate/onDestroyです。アプリはここでライブラリ セッション、プレーヤー、その他のリソースを割り当てたり解放したりします。標準のサービス ライフサイクル メソッドに加えて、アプリは- onGetSession(MediaSession.ControllerInfo)をオーバーライドして、- onCreateでビルドされた- MediaLibrarySessionを返す必要があります。
- MediaLibraryService.MediaLibrarySessionCallback を実装する: セッションを構築するには、実際のドメイン API メソッドを実装する - MediaLibraryService.MediaLibrarySessionCallbackが必要です。そのため、レガシー サービスの API メソッドをオーバーライドする代わりに、- MediaLibrarySession.Callbackのメソッドをオーバーライドします。- コールバックは、 - MediaLibrarySessionのビルドに使用されます。- mediaLibrarySession = MediaLibrarySession.Builder(this, player, MySessionCallback()) .build()- API ドキュメントで MediaLibrarySessionCallback の完全な API を確認してください。 
- MediaSession.Callback.onAddMediaItems()を実装する: コールバック- onAddMediaItems(MediaSession, ControllerInfo, List<MediaItem>)は、下位互換性のある方法で再生のためにメディア アイテムをプレーヤーに追加する、さまざまな現行の API メソッドとレガシー API メソッドを提供します。これには、Media3 コントローラの- MediaController.set/addMediaItems()メソッドと、以前の API の- TransportControls.prepareFrom*/playFrom*メソッドが含まれます。コールバックの実装例については、セッション デモアプリの- PlaybackServiceをご覧ください。
- AndroidX Media3 では、MediaBrowserCompat.MediaItem と MediaMetadataCompat の代わりに - androidx.media3.common.MediaItemが使用されています。レガシー クラスに関連付けられているコードの部分は、それに応じて変更するか、Media3 の- MediaItemにマッピングする必要があります。
- MediaBrowserServiceCompatのデタッチ可能な- Resultアプローチとは対照的に、一般的な非同期プログラミング モデルが- Futuresに変更されました。サービス実装では、結果を切り離したり、値を直接返すために即時 Future を返したりする代わりに、非同期- ListenableFutureを返すことができます。
 
PlayerNotificationManager を削除
MediaLibraryService はメディア通知を自動的にサポートします。また、MediaLibraryService または MediaSessionService を使用している場合は PlayerNotificationManager を削除できます。
アプリは、DefaultMediaNotificationProvider を置き換えるカスタム MediaNotification.Provider を onCreate() に設定することで、通知をカスタマイズできます。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 の使用に関する lint エラーが表示されることがあります。これらの API は安全に使用でき、lint エラーは新しいバイナリ互換性保証の副産物です。厳密なバイナリ互換性が必要ない場合は、@OptIn アノテーションを使用してこれらのエラーを安全に抑制できます。
背景
ExoPlayer v1 と v2 のどちらも、ライブラリのバイナリ互換性について、後続のバージョン間で厳密な保証を提供していません。ExoPlayer API サーフェスは、アプリが再生のほぼすべての側面をカスタマイズできるように、設計上非常に大きくなっています。ExoPlayer の後続バージョンでは、シンボルの名前変更やその他の互換性を破る変更(インターフェースの新しい必須メソッドなど)が導入されることがありました。ほとんどの場合、これらの破損は、古いシンボルを数バージョンにわたって非推奨にするとともに新しいシンボルを導入することで軽減され、デベロッパーが使用法を移行する時間を確保できましたが、常に可能とは限りませんでした。
これらの破壊的変更により、ExoPlayer v1 および v2 ライブラリのユーザーに次の 2 つの問題が発生しました。
- ExoPlayer のバージョンからへのアップグレードにより、コードのコンパイルが停止する可能性があります。
- ExoPlayer に直接依存し、中間ライブラリ経由でも依存しているアプリは、両方の依存関係が同じバージョンであることを確認する必要がありました。そうしないと、バイナリの互換性の問題により、実行時にクラッシュが発生する可能性がありました。
Media3 の改善
Media3 は、API サーフェスのサブセットのバイナリ互換性を保証します。バイナリ互換性が保証されない部分は、@UnstableApi でマークされています。この区別を明確にするため、不安定な API シンボルの使用は、@OptIn でアノテーションが付けられていない限り、lint エラーを生成します。
ExoPlayer v2 から Media3 に移行すると、不安定な API の lint エラーが多数表示されることがあります。このため、Media3 は ExoPlayer v2 よりも「安定性が低い」ように見えることがあります。実際、そうしたサイトにお金を払う必要はありません。Media3 API の「不安定」な部分は、ExoPlayer v2 API サーフェス全体と同じレベルの安定性を備えています。また、安定版の Media3 API サーフェスの保証は、ExoPlayer v2 ではまったく利用できません。違いは、安定性のレベルが異なる場合に lint エラーで警告が表示されるようになっただけです。
不安定な API の lint エラーを処理
@OptIn を使用して不安定な API の Java と Kotlin の使用法にアノテーションを付ける方法について詳しくは、これらの lint エラーに関するトラブルシューティング セクションをご覧ください。
サポート終了 API
非推奨の API への呼び出しは、Android Studio で取り消し線で示されます。このような呼び出しは、適切な代替手段に置き換えることをおすすめします。シンボルにマウスオーバーすると、代わりにどの API を使用するかを示す JavaDoc が表示されます。
 
    コードサンプルとデモアプリ
- AndroidX Media3 セッションのデモアプリ(モバイルと WearOS)
- カスタム アクション
- システム UI 通知、MediaButton/BT
- Google アシスタントの再生コントロール
 
- UAMP: Android メディア プレーヤー(ブランチ media3)(モバイル、AutomotiveOS)
- システム UI 通知、MediaButton/BT、再生の再開
- Google アシスタント/Wear OS の再生コントロール
- AutomotiveOS: カスタム コマンドとログイン
 
