Sesi media menyediakan cara universal untuk berinteraksi dengan pemutar
audio atau video. Di Media3, pemutar default adalah class ExoPlayer
, yang mengimplementasikan
antarmuka Player
. Menghubungkan sesi media ke pemutar memungkinkan aplikasi
mengumumkan pemutaran media secara eksternal dan menerima perintah pemutaran dari
sumber eksternal.
Perintah dapat berasal dari tombol fisik seperti tombol putar di headset atau remote control TV. Perintah ini juga dapat berasal dari aplikasi klien yang memiliki pengontrol media, seperti memberikan perintah "jeda" ke Asisten Google. Sesi media mendelegasikan perintah ini ke pemutar aplikasi media.
Kapan harus memilih sesi media
Saat menerapkan MediaSession
, Anda mengizinkan pengguna mengontrol pemutaran:
- Melalui headphone mereka. Sering kali ada tombol atau interaksi sentuh yang dapat dilakukan pengguna di headphone untuk memutar atau menjeda media atau membuka trek berikutnya atau sebelumnya.
- Dengan berbicara kepada Asisten Google. Pola umum adalah mengucapkan "Ok Google, jeda" untuk menjeda media apa pun yang sedang diputar di perangkat.
- Melalui smartwatch Wear OS. Hal ini memungkinkan akses yang lebih mudah ke kontrol pemutaran yang paling umum saat memutar di ponsel.
- Melalui Kontrol media. Carousel ini menampilkan kontrol untuk setiap sesi media yang berjalan.
- Di TV. Memungkinkan tindakan dengan tombol pemutaran fisik, kontrol pemutaran platform, dan pengelolaan daya (misalnya, jika TV, soundbar, atau penerima A/V dinonaktifkan atau input diubah, pemutaran akan berhenti di aplikasi).
- Dan proses eksternal lainnya yang perlu memengaruhi pemutaran.
Hal ini sangat cocok untuk banyak kasus penggunaan. Secara khusus, Anda harus mempertimbangkan
penggunaan MediaSession
jika:
- Anda melakukan streaming konten video panjang, seperti film atau TV live.
- Anda melakukan streaming konten audio berdurasi panjang, seperti podcast atau playlist musik.
- Anda sedang mem-build aplikasi TV.
Namun, tidak semua kasus penggunaan cocok dengan MediaSession
. Anda mungkin ingin
hanya menggunakan Player
dalam kasus berikut:
- Anda menampilkan konten berdurasi pendek, yang tidak memerlukan kontrol eksternal atau pemutaran latar belakang.
- Tidak ada satu video aktif, seperti pengguna men-scroll daftar dan beberapa video ditampilkan di layar secara bersamaan.
- Anda memutar video pengantar atau penjelasan satu kali, yang Anda harapkan akan ditonton secara aktif oleh pengguna tanpa memerlukan kontrol pemutaran eksternal.
- Konten Anda sensitif terhadap privasi dan Anda tidak ingin proses eksternal mengakses metadata media (misalnya mode Samaran di browser).
Jika kasus penggunaan Anda tidak sesuai dengan salah satu yang tercantum di atas, pertimbangkan apakah Anda
memungkinkan aplikasi melanjutkan pemutaran saat pengguna tidak berinteraksi secara aktif
dengan konten. Jika jawabannya ya, sebaiknya pilih
MediaSession
. Jika jawabannya tidak, sebaiknya gunakan Player
sebagai gantinya.
Membuat sesi media
Sesi media berdampingan dengan pemutar yang dikelolanya. Anda dapat membuat
sesi media dengan objek Context
dan Player
. Anda harus membuat dan
melakukan inisialisasi sesi media saat diperlukan, seperti metode siklus proses onStart()
atau
onResume()
dari Activity
atau Fragment
, atau metode onCreate()
dari Service
yang memiliki sesi media dan pemutar terkaitnya.
Untuk membuat sesi media, lakukan inisialisasi Player
dan berikan ke
MediaSession.Builder
seperti ini:
Kotlin
val player = ExoPlayer.Builder(context).build() val mediaSession = MediaSession.Builder(context, player).build()
Java
ExoPlayer player = new ExoPlayer.Builder(context).build(); MediaSession mediaSession = new MediaSession.Builder(context, player).build();
Penanganan status otomatis
Library Media3 otomatis memperbarui sesi media menggunakan status pemutar. Dengan demikian, Anda tidak perlu menangani pemetaan dari pemain ke sesi secara manual.
Hal ini berbeda dengan sesi media platform tempat Anda perlu membuat dan
memelihara PlaybackState
secara independen dari pemutar itu sendiri, misalnya untuk
menunjukkan error.
ID sesi unik
Secara default, MediaSession.Builder
membuat sesi dengan string kosong sebagai ID sesi. Hal ini cukup jika aplikasi hanya ingin membuat satu
instance sesi, yang merupakan kasus paling umum.
Jika aplikasi ingin mengelola beberapa instance sesi secara bersamaan, aplikasi
harus memastikan bahwa ID sesi setiap sesi bersifat unik. ID sesi dapat ditetapkan saat mem-build sesi dengan MediaSession.Builder.setId(String id)
.
Jika Anda melihat IllegalStateException
yang membuat aplikasi error dengan pesan error
IllegalStateException: Session ID must be unique. ID=
, kemungkinan
sesi telah dibuat secara tidak terduga sebelum instance yang dibuat sebelumnya
dengan ID yang sama telah dirilis. Untuk menghindari kebocoran sesi akibat
error pemrograman, kasus tersebut akan terdeteksi dan diberi tahu dengan menampilkan
pengecualian.
Memberikan kontrol kepada klien lain
Sesi media adalah kunci untuk mengontrol pemutaran. Dengan begitu, Anda dapat merutekan perintah dari sumber eksternal ke pemutar yang melakukan tugas memutar media. Sumber ini dapat berupa tombol fisik seperti tombol putar di headset atau remote control TV, atau perintah tidak langsung seperti memberi perintah "jeda" ke Asisten Google. Demikian pula, Anda dapat memberikan akses ke sistem Android untuk memfasilitasi notifikasi dan kontrol layar kunci, atau ke smartwatch Wear OS sehingga Anda dapat mengontrol pemutaran dari tampilan jam. Klien eksternal dapat menggunakan pengontrol media untuk mengeluarkan perintah pemutaran ke aplikasi media Anda. Perintah ini diterima oleh sesi media Anda, yang pada akhirnya mendelegasikan perintah ke pemutar media.

Saat pengontrol akan terhubung ke sesi media Anda, metode
onConnect()
akan dipanggil. Anda dapat menggunakan ControllerInfo
yang disediakan untuk memutuskan apakah akan menerima
atau menolak
permintaan. Lihat contoh penerimaan permintaan koneksi di bagian Mendeklarasikan
perintah kustom.
Setelah terhubung, pengontrol dapat mengirim perintah pemutaran ke sesi. Kemudian,
sesi mendelegasikan perintah tersebut ke pemutar. Perintah pemutaran dan playlist
yang ditentukan di antarmuka Player
akan otomatis ditangani oleh
sesi.
Metode callback lainnya memungkinkan Anda menangani, misalnya, permintaan untuk perintah
kustom dan mengubah playlist. Callback
ini juga menyertakan objek ControllerInfo
sehingga Anda dapat mengubah cara
merespons setiap permintaan berdasarkan per pengontrol.
Mengubah playlist
Sesi media dapat langsung mengubah playlist pemutarnya seperti yang dijelaskan dalam
panduan ExoPlayer untuk playlist.
Pengontrol juga dapat mengubah playlist jika
COMMAND_SET_MEDIA_ITEM
atau COMMAND_CHANGE_MEDIA_ITEMS
tersedia untuk
pengontrol.
Saat menambahkan item baru ke playlist, pemutar biasanya memerlukan instance MediaItem
dengan
URI yang ditentukan
agar dapat diputar. Secara default, item yang baru ditambahkan akan otomatis diteruskan
ke metode pemutar seperti player.addMediaItem
jika memiliki URI yang ditentukan.
Jika ingin menyesuaikan instance MediaItem
yang ditambahkan ke pemutar, Anda dapat
mengganti
onAddMediaItems()
.
Langkah ini diperlukan jika Anda ingin mendukung pengontrol yang meminta media
tanpa URI yang ditentukan. Sebagai gantinya, MediaItem
biasanya memiliki
satu atau beberapa kolom berikut yang ditetapkan untuk menjelaskan media yang diminta:
MediaItem.id
: ID generik yang mengidentifikasi media.MediaItem.RequestMetadata.mediaUri
: URI permintaan yang dapat menggunakan skema kustom dan tidak harus dapat diputar langsung oleh pemutar.MediaItem.RequestMetadata.searchQuery
: Kueri penelusuran tekstual, misalnya dari Asisten Google.MediaItem.MediaMetadata
: Metadata terstruktur seperti 'judul' atau 'artis'.
Untuk opsi penyesuaian lainnya bagi playlist yang benar-benar baru, Anda juga dapat mengganti
onSetMediaItems()
yang memungkinkan Anda menentukan item dan posisi awal dalam playlist. Misalnya,
Anda dapat memperluas satu item yang diminta ke seluruh playlist dan menginstruksikan
pemutar untuk memulai dari indeks item yang awalnya diminta. Contoh implementasi onSetMediaItems()
dengan fitur ini dapat ditemukan di aplikasi demo sesi.
Mengelola preferensi tombol media
Setiap pengontrol, misalnya UI Sistem, Android Auto, atau Wear OS, dapat membuat
keputusannya sendiri tentang tombol mana yang akan ditampilkan kepada pengguna. Untuk menunjukkan kontrol pemutaran yang ingin Anda tampilkan kepada pengguna, Anda dapat menentukan preferensi tombol media di MediaSession
. Preferensi ini terdiri dari daftar instance CommandButton
yang diurutkan, masing-masing menentukan preferensi untuk tombol di
antarmuka pengguna.
Menentukan tombol perintah
Instance CommandButton
digunakan untuk menentukan preferensi tombol media. Setiap
tombol menentukan tiga aspek elemen UI yang diinginkan:
- Ikon, yang menentukan tampilan visual. Ikon harus ditetapkan ke salah satu
konstanta yang telah ditentukan sebelumnya saat membuat
CommandButton.Builder
. Perhatikan bahwa ini bukan Bitmap atau resource gambar yang sebenarnya. Konstanta generik membantu pengontrol memilih resource yang sesuai untuk tampilan dan nuansa yang konsisten dalam UI-nya sendiri. Jika tidak ada konstanta ikon standar yang sesuai dengan kasus penggunaan Anda, Anda dapat menggunakansetCustomIconResId
. - Perintah, yang menentukan tindakan yang dipicu saat pengguna berinteraksi dengan
tombol. Anda dapat menggunakan
setPlayerCommand
untukPlayer.Command
, atausetSessionCommand
untukSessionCommand
standar atau kustom. - Slot, yang menentukan tempat tombol harus ditempatkan di UI pengontrol. Kolom ini bersifat opsional dan ditetapkan secara otomatis berdasarkan Ikon dan Perintah. Misalnya, ini memungkinkan untuk menentukan bahwa tombol harus ditampilkan di area navigasi 'maju' UI, bukan area 'overflow' default.
Kotlin
val button = CommandButton.Builder(CommandButton.ICON_SKIP_FORWARD_15) .setSessionCommand(SessionCommand(CUSTOM_ACTION_ID, Bundle.EMPTY)) .setSlots(CommandButton.SLOT_FORWARD) .build()
Java
CommandButton button = new CommandButton.Builder(CommandButton.ICON_SKIP_FORWARD_15) .setSessionCommand(new SessionCommand(CUSTOM_ACTION_ID, Bundle.EMPTY)) .setSlots(CommandButton.SLOT_FORWARD) .build();
Saat preferensi tombol media di-resolve, algoritma berikut akan diterapkan:
- Untuk setiap
CommandButton
di preferensi tombol media, tempatkan tombol di slot pertama yang tersedia dan diizinkan. - Jika salah satu slot tengah, maju, dan mundur tidak diisi dengan tombol, tambahkan tombol default untuk slot ini.
Anda dapat menggunakan CommandButton.DisplayConstraints
untuk membuat pratinjau cara
preferensi tombol media akan di-resolve, bergantung pada batasan tampilan
UI.
Menetapkan preferensi tombol media
Cara termudah untuk menetapkan preferensi tombol media adalah dengan menentukan daftar saat
mem-build MediaSession
. Atau, Anda dapat mengganti
MediaSession.Callback.onConnect
untuk menyesuaikan preferensi tombol media untuk
setiap pengontrol yang terhubung.
Kotlin
val mediaSession = MediaSession.Builder(context, player) .setMediaButtonPreferences(ImmutableList.of(likeButton, favoriteButton)) .build()
Java
MediaSession mediaSession = new MediaSession.Builder(context, player) .setMediaButtonPreferences(ImmutableList.of(likeButton, favoriteButton)) .build();
Memperbarui preferensi tombol media setelah interaksi pengguna
Setelah menangani interaksi dengan pemutar, Anda dapat memperbarui
tombol yang ditampilkan di UI pengontrol. Contoh umum adalah tombol tombol
yang mengubah ikon dan tindakannya setelah memicu tindakan yang terkait dengan
tombol ini. Untuk memperbarui preferensi tombol media, Anda dapat menggunakan
MediaSession.setMediaButtonPreferences
untuk memperbarui preferensi untuk
semua pengontrol atau pengontrol tertentu:
Kotlin
// Handle "favoritesButton" action, replace by opposite button mediaSession.setMediaButtonPreferences( ImmutableList.of(likeButton, removeFromFavoritesButton))
Java
// Handle "favoritesButton" action, replace by opposite button mediaSession.setMediaButtonPreferences( ImmutableList.of(likeButton, removeFromFavoritesButton));
Menambahkan perintah kustom dan menyesuaikan perilaku default
Perintah pemutar yang tersedia dapat diperluas dengan perintah kustom dan Anda juga dapat mencegat perintah pemutar dan tombol media yang masuk untuk mengubah perilaku default.
Mendeklarasikan dan menangani perintah kustom
Aplikasi media dapat menentukan perintah kustom yang misalnya dapat digunakan di
preferensi tombol media. Misalnya, Anda mungkin
ingin menerapkan tombol yang memungkinkan pengguna menyimpan item media ke daftar
item favorit. MediaController
mengirimkan perintah kustom dan
MediaSession.Callback
menerimanya.
Untuk menentukan perintah kustom, Anda perlu mengganti
MediaSession.Callback.onConnect()
untuk menetapkan perintah kustom yang tersedia untuk
setiap pengontrol yang terhubung.
Kotlin
private class CustomMediaSessionCallback: MediaSession.Callback { // Configure commands available to the controller in onConnect() override fun onConnect( session: MediaSession, controller: MediaSession.ControllerInfo ): MediaSession.ConnectionResult { val sessionCommands = ConnectionResult.DEFAULT_SESSION_COMMANDS.buildUpon() .add(SessionCommand(SAVE_TO_FAVORITES, Bundle.EMPTY)) .build() return AcceptedResultBuilder(session) .setAvailableSessionCommands(sessionCommands) .build() } }
Java
class CustomMediaSessionCallback implements MediaSession.Callback { // Configure commands available to the controller in onConnect() @Override public ConnectionResult onConnect( MediaSession session, ControllerInfo controller) { SessionCommands sessionCommands = ConnectionResult.DEFAULT_SESSION_COMMANDS.buildUpon() .add(new SessionCommand(SAVE_TO_FAVORITES, new Bundle())) .build(); return new AcceptedResultBuilder(session) .setAvailableSessionCommands(sessionCommands) .build(); } }
Untuk menerima permintaan perintah kustom dari MediaController
, ganti
metode onCustomCommand()
di Callback
.
Kotlin
private class CustomMediaSessionCallback: MediaSession.Callback { ... override fun onCustomCommand( session: MediaSession, controller: MediaSession.ControllerInfo, customCommand: SessionCommand, args: Bundle ): ListenableFuture<SessionResult> { if (customCommand.customAction == SAVE_TO_FAVORITES) { // Do custom logic here saveToFavorites(session.player.currentMediaItem) return Futures.immediateFuture( SessionResult(SessionResult.RESULT_SUCCESS) ) } ... } }
Java
class CustomMediaSessionCallback implements MediaSession.Callback { ... @Override public ListenableFuture<SessionResult> onCustomCommand( MediaSession session, ControllerInfo controller, SessionCommand customCommand, Bundle args ) { if(customCommand.customAction.equals(SAVE_TO_FAVORITES)) { // Do custom logic here saveToFavorites(session.getPlayer().getCurrentMediaItem()); return Futures.immediateFuture( new SessionResult(SessionResult.RESULT_SUCCESS) ); } ... } }
Anda dapat melacak pengontrol media mana yang membuat permintaan menggunakan
properti packageName
dari objek MediaSession.ControllerInfo
yang
diteruskan ke metode Callback
. Dengan cara ini, Anda dapat menyesuaikan perilaku
aplikasi sebagai respons terhadap perintah tertentu jika berasal dari sistem,
aplikasi Anda sendiri, atau aplikasi klien lainnya.
Menyesuaikan perintah pemain default
Semua perintah default dan penanganan status didelegasikan ke Player
yang ada di
MediaSession
. Untuk menyesuaikan perilaku perintah yang ditentukan di antarmuka Player
, seperti play()
atau seekToNext()
, gabungkan Player
dalam ForwardingSimpleBasePlayer
sebelum meneruskannya ke MediaSession
:
Kotlin
val player = (logic to build a Player instance) val forwardingPlayer = object : ForwardingSimpleBasePlayer(player) { // Customizations } val mediaSession = MediaSession.Builder(context, forwardingPlayer).build()
Java
ExoPlayer player = (logic to build a Player instance) ForwardingSimpleBasePlayer forwardingPlayer = new ForwardingSimpleBasePlayer(player) { // Customizations }; MediaSession mediaSession = new MediaSession.Builder(context, forwardingPlayer).build();
Untuk informasi selengkapnya tentang ForwardingSimpleBasePlayer
, lihat panduan ExoPlayer
Penyesuaian.
Mengidentifikasi pengontrol yang meminta perintah pemain
Saat panggilan ke metode Player
berasal dari MediaController
, Anda dapat
mengidentifikasi sumber asal dengan MediaSession.controllerForCurrentRequest
dan memperoleh ControllerInfo
untuk permintaan saat ini:
Kotlin
class CallerAwarePlayer(player: Player) : ForwardingSimpleBasePlayer(player) { override fun handleSeek( mediaItemIndex: Int, positionMs: Long, seekCommand: Int, ): ListenableFuture<*> { Log.d( "caller", "seek operation from package ${session.controllerForCurrentRequest?.packageName}", ) return super.handleSeek(mediaItemIndex, positionMs, seekCommand) } }
Java
public class CallerAwarePlayer extends ForwardingSimpleBasePlayer { public CallerAwarePlayer(Player player) { super(player); } @Override protected ListenableFuture<?> handleSeek( int mediaItemIndex, long positionMs, int seekCommand) { Log.d( "caller", "seek operation from package: " + session.getControllerForCurrentRequest().getPackageName()); return super.handleSeek(mediaItemIndex, positionMs, seekCommand); } }
Menyesuaikan penanganan tombol media
Tombol media adalah tombol hardware yang ada di perangkat Android dan perangkat periferal
lainnya, seperti tombol putar/jeda di headset Bluetooth. Media3 menangani
peristiwa tombol media untuk Anda saat tiba di sesi dan memanggil
metode Player
yang sesuai di pemutar sesi.
Sebaiknya tangani semua peristiwa tombol media yang masuk dalam
metode Player
yang sesuai. Untuk kasus penggunaan lanjutan lainnya, peristiwa tombol
media dapat dicegat di MediaSession.Callback.onMediaButtonEvent(Intent)
.
Penanganan dan pelaporan error
Ada dua jenis error yang dikeluarkan dan dilaporkan sesi ke pengontrol. Error fatal melaporkan kegagalan pemutaran teknis pemutar sesi yang mengganggu pemutaran. Error fatal dilaporkan ke pengontrol secara otomatis saat terjadi. Error tidak fatal adalah error non-teknis atau kebijakan yang tidak mengganggu pemutaran dan dikirim ke pengontrol oleh aplikasi secara manual.
Error pemutaran fatal
Error pemutaran fatal dilaporkan ke sesi oleh pemutar, lalu
dilaporkan ke pengontrol untuk memanggil melalui
Player.Listener.onPlayerError(PlaybackException)
dan
Player.Listener.onPlayerErrorChanged(@Nullable PlaybackException)
.
Dalam kasus seperti itu, status pemutaran akan ditransisikan ke STATE_IDLE
dan
MediaController.getPlaybackError()
menampilkan PlaybackException
yang menyebabkan
transisi. Pengontrol dapat memeriksa PlayerException.errorCode
untuk mendapatkan informasi tentang alasan error.
Untuk interoperabilitas, error fatal direplikasi ke sesi platform dengan
mentransisikan statusnya ke STATE_ERROR
dan menetapkan kode dan pesan error
sesuai dengan PlaybackException
.
Penyesuaian error fatal
Untuk memberikan informasi yang dilokalkan dan bermakna kepada pengguna, kode error,
pesan error, dan tambahan error dari error pemutaran fatal dapat disesuaikan dengan
menggunakan ForwardingPlayer
saat mem-build sesi:
Kotlin
val forwardingPlayer = ErrorForwardingPlayer(player) val session = MediaSession.Builder(context, forwardingPlayer).build()
Java
Player forwardingPlayer = new ErrorForwardingPlayer(player); MediaSession session = new MediaSession.Builder(context, forwardingPlayer).build();
Pemutar penerusan dapat menggunakan ForwardingSimpleBasePlayer
untuk mencegat
error dan menyesuaikan kode error, pesan, atau tambahan. Dengan cara yang sama, Anda juga dapat
membuat error baru yang tidak ada di pemutar asli:
Kotlin
class ErrorForwardingPlayer (private val context: Context, player: Player) : ForwardingSimpleBasePlayer(player) { override fun getState(): State { var state = super.getState() if (state.playerError != null) { state = state.buildUpon() .setPlayerError(customizePlaybackException(state.playerError!!)) .build() } return state } fun customizePlaybackException(error: PlaybackException): PlaybackException { val buttonLabel: String val errorMessage: String when (error.errorCode) { PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW -> { buttonLabel = context.getString(R.string.err_button_label_restart_stream) errorMessage = context.getString(R.string.err_msg_behind_live_window) } else -> { buttonLabel = context.getString(R.string.err_button_label_ok) errorMessage = context.getString(R.string.err_message_default) } } val extras = Bundle() extras.putString("button_label", buttonLabel) return PlaybackException(errorMessage, error.cause, error.errorCode, extras) } }
Java
class ErrorForwardingPlayer extends ForwardingSimpleBasePlayer { private final Context context; public ErrorForwardingPlayer(Context context, Player player) { super(player); this.context = context; } @Override protected State getState() { State state = super.getState(); if (state.playerError != null) { state = state.buildUpon() .setPlayerError(customizePlaybackException(state.playerError)) .build(); } return state; } private PlaybackException customizePlaybackException(PlaybackException error) { String buttonLabel; String errorMessage; switch (error.errorCode) { case PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW: buttonLabel = context.getString(R.string.err_button_label_restart_stream); errorMessage = context.getString(R.string.err_msg_behind_live_window); break; default: buttonLabel = context.getString(R.string.err_button_label_ok); errorMessage = context.getString(R.string.err_message_default); break; } Bundle extras = new Bundle(); extras.putString("button_label", buttonLabel); return new PlaybackException(errorMessage, error.getCause(), error.errorCode, extras); } }
Error non-fatal
Error non-fatal yang tidak berasal dari pengecualian teknis dapat dikirim oleh aplikasi ke semua atau ke pengontrol tertentu:
Kotlin
val sessionError = SessionError( SessionError.ERROR_SESSION_AUTHENTICATION_EXPIRED, context.getString(R.string.error_message_authentication_expired), ) // Option 1: Sending a nonfatal error to all controllers. mediaSession.sendError(sessionError) // Option 2: Sending a nonfatal error to the media notification controller only // to set the error code and error message in the playback state of the platform // media session. mediaSession.mediaNotificationControllerInfo?.let { mediaSession.sendError(it, sessionError) }
Java
SessionError sessionError = new SessionError( SessionError.ERROR_SESSION_AUTHENTICATION_EXPIRED, context.getString(R.string.error_message_authentication_expired)); // Option 1: Sending a nonfatal error to all controllers. mediaSession.sendError(sessionError); // Option 2: Sending a nonfatal error to the media notification controller only // to set the error code and error message in the playback state of the platform // media session. ControllerInfo mediaNotificationControllerInfo = mediaSession.getMediaNotificationControllerInfo(); if (mediaNotificationControllerInfo != null) { mediaSession.sendError(mediaNotificationControllerInfo, sessionError); }
Saat error non-fatal dikirim ke pengontrol notifikasi media, kode error
dan pesan error direplikasi ke sesi media platform, sedangkan
PlaybackState.state
tidak diubah menjadi STATE_ERROR
.
Menerima error non-fatal
MediaController
menerima error non-fatal dengan menerapkan
MediaController.Listener.onError
:
Kotlin
val future = MediaController.Builder(context, sessionToken) .setListener(object : MediaController.Listener { override fun onError(controller: MediaController, sessionError: SessionError) { // Handle nonfatal error. } }) .buildAsync()
Java
MediaController.Builder future = new MediaController.Builder(context, sessionToken) .setListener( new MediaController.Listener() { @Override public void onError(MediaController controller, SessionError sessionError) { // Handle nonfatal error. } });