Tombol media adalah tombol hardware yang ada di perangkat Android dan perangkat periferal lainnya, seperti tombol jeda/putar di headset Bluetooth. Saat pengguna menekan tombol media, Android akan membuat KeyEvent
yang berisi kode kunci yang mengidentifikasi tombol itu. Kode kunci untuk tombol media KeyEvents adalah konstanta yang dimulai dengan KEYCODE_MEDIA
(misalnya KEYCODE_MEDIA_PLAY
).
Aplikasi harus dapat menangani peristiwa tombol media dalam tiga kasus, dalam urutan prioritas berikut:
- Saat aktivitas UI aplikasi terlihat
- Saat aktivitas UI tersembunyi dan sesi media aplikasi aktif
- Saat aktivitas UI tersembunyi dan sesi media aplikasi tidak aktif dan perlu dimulai ulang
Menangani tombol media dalam aktivitas latar depan
Aktivitas latar depan menerima peristiwa kunci tombol media dalam metode onKeyDown()
-nya. Bergantung pada versi Android yang berjalan, ada dua cara yang digunakan sistem untuk merutekan peristiwa ini ke pengontrol media:
- Jika Anda menjalankan Android 5.0 (API level 21) atau yang lebih baru, panggil
FLAG_HANDLES_MEDIA_BUTTONS
MediaBrowserCompat.ConnectionCallback.onConnected
. Tindakan ini akan otomatis memanggildispatchMediaButtonEvent()
pengontrol media Anda, yang menerjemahkan kode kunci ke callback sesi media. - Sebelum Android 5.0 (API level 21), Anda perlu memodifikasi
onKeyDown()
untuk menangani peristiwa itu sendiri. (Lihat Menangani tombol media dalam sesi media yang aktif untuk penjelasan selengkapnya.) Cuplikan kode berikut menunjukkan cara mengintersep kode kunci dan memanggil dispatchMediaButtonEvent(). Pastikan untuk menampilkantrue
yang mengindikasikan bahwa peristiwa itu telah ditangani:Kotlin
fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { return super.onKeyDown(keyCode, event) } when (keyCode) { KeyEvent.KEYCODE_MEDIA_PLAY -> { yourMediaController.dispatchMediaButtonEvent(event) return true } } return super.onKeyDown(keyCode, event) }
Java
@Override boolean onKeyDown(int keyCode, KeyEvent event) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { return super.onKeyDown(keyCode, event); } switch (keyCode) { case KeyEvent.KEYCODE_MEDIA_PLAY: yourMediaController.dispatchMediaButtonEvent(event); return true; } return super.onKeyDown(keyCode, event); }
Mencari sesi media
Jika aktivitas latar depan tidak menangani peristiwa ini, Android akan mencoba menemukan sesi media yang dapat menanganinya. Sekali lagi, bergantung pada versi Android yang berjalan, ada dua cara untuk menelusuri sesi media:
Jika Anda menjalankan Android 8.0 (API level 26) atau yang lebih baru, sistem akan mencoba menemukan aplikasi terakhir yang memutar audio secara lokal dengan MediaSession. Jika sesi itu masih aktif, Android akan mengirim peristiwa tersebut langsung ke sana. Sebaliknya, jika sesi tidak aktif dan memiliki penerima tombol media, Android akan mengirim peristiwa itu ke penerima, yang akan memulai ulang sesi sehingga dapat menerima peristiwa tersebut. (Lihat Menggunakan tombol media untuk memulai ulang sesi media yang tidak aktif untuk penjelasan selengkapnya.) Jika sesi tidak memiliki penerima tombol media, sistem akan membuang peristiwa tombol media itu dan tidak akan ada apa pun yang terjadi. Logika ini ditampilkan dalam diagram berikut:
Sebelum Android 8.0 (API level 26), sistem mencoba mengirim peristiwa ke sesi media yang aktif. Jika ada beberapa sesi media yang aktif, Android akan mencoba memilih sesi media yang sedang bersiap diputar (buffering/tersambung), sedang diputar, atau dijeda, bukan sesi yang dihentikan. (Lihat Menangani tombol media dalam sesi media yang aktif untuk penjelasan selengkapnya.) Jika tidak ada sesi yang aktif, Android akan mencoba mengirim peristiwa ke sesi yang paling terakhir aktif. (Lihat Menggunakan tombol media untuk memulai ulang sesi media yang tidak aktif untuk penjelasan selengkapnya.) Logika ini ditampilkan dalam diagram berikut:
Menangani tombol media dalam sesi media yang aktif
Di Android 5.0 (API level 21) dan yang lebih baru, Android akan otomatis mengirim peristiwa tombol media ke sesi media aktif Anda dengan memanggil onMediaButtonEvent()
.
Secara default, callback ini menerjemahkan KeyEvent menjadi metode Callback sesi media yang sesuai, yang cocok dengan kode kuncinya.
Sebelum Android 5.0 (API level 21), Android akan menangani peristiwa tombol media dengan menyiarkan intent yang memuat tindakan ACTION_MEDIA_BUTTON
. Aplikasi Anda harus mendaftarkan BroadcastReceiver untuk mengintersep intent tersebut. Class MediaButtonReceiver
dirancang khusus untuk keperluan ini. Ini adalah class praktis di library media-compat Android yang menangani ACTION_MEDIA_BUTTON
dan menerjemahkan Intent yang masuk menjadi panggilan metode MediaSessionCompat.Callback
yang sesuai.
MediaButtonReceiver
adalah BroadcastReceiver yang berumur pendek. Class ini meneruskan intent yang masuk ke layanan yang mengelola sesi media Anda. Jika ingin menggunakan tombol media di sistem sebelum Android 5.0, Anda harus menyertakan MediaButtonReceiver
dalam manifes dengan filter intent MEDIA_BUTTON
.:
<receiver android:name="android.support.v4.media.session.MediaButtonReceiver" >
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
BroadcastReceiver
meneruskan intent ke layanan Anda. Untuk mengurai intent ini dan menghasilkan callback ke sesi media Anda, sertakan metode MediaButtonReceiver.handleIntent()
dalam onStartCommand()
layanan Anda.
Tindakan ini akan menerjemahkan kode kunci menjadi metode callback sesi yang sesuai.
Kotlin
private val mediaSessionCompat: MediaSessionCompat = ... override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { MediaButtonReceiver.handleIntent(mediaSessionCompat, intent) return super.onStartCommand(intent, flags, startId) }
Java
private MediaSessionCompat mediaSessionCompat = ...; public int onStartCommand(Intent intent, int flags, int startId) { MediaButtonReceiver.handleIntent(mediaSessionCompat, intent); return super.onStartCommand(intent, flags, startId); }
Menggunakan tombol media untuk memulai ulang sesi media yang tidak aktif
Jika dapat mengidentifikasi sesi media yang terakhir aktif, Android akan mencoba memulai ulang sesi itu dengan mengirim Intent ACTION_MEDIA_BUTTON
ke komponen yang terdaftar di manifes (misalnya layanan atau BroadcastReceiver
).
Dengan begitu, aplikasi Anda akan dapat memulai ulang pemutaran saat UI-nya tidak terlihat, seperti yang terjadi di sebagian besar aplikasi audio.
Perilaku ini diaktifkan secara otomatis jika Anda menggunakan MediaSessionCompat
. Jika Anda menggunakan MediaSession
dari framework Android atau Support Library 24.0.0 hingga 25.1.1, Anda harus memanggil setMediaButtonReceiver
untuk mengizinkan tombol media memulai ulang sesi media yang tidak aktif.
Anda dapat menonaktifkan perilaku ini di Android 5.0 (API level 21) dan yang lebih tinggi dengan menetapkan penerima tombol media ke null:
Kotlin
// Create a MediaSessionCompat mediaSession = MediaSessionCompat(context, LOG_TAG) mediaSession.setMediaButtonReceiver(null)
Java
// Create a MediaSessionCompat mediaSession = new MediaSessionCompat(context, LOG_TAG); mediaSession.setMediaButtonReceiver(null);
Menyesuaikan pengendali tombol media
Perilaku default untuk onMediaButtonEvent()
adalah mengekstrak kode kunci dan menggunakan status terkini sesi media dan daftar tindakan yang didukung untuk menentukan metode yang akan dihubungi. Misalnya, KEYCODE_MEDIA_PLAY
memanggil onPlay()
.
Untuk memberikan pengalaman tombol media yang konsisten di semua aplikasi, sebaiknya Anda menggunakan perilaku default ini dan hanya meninggalkannya untuk keperluan tertentu. Jika tombol media memerlukan penanganan khusus, ganti metode onMediaButtonEvent()
callback Anda, ekstrak KeyEvent
menggunakan intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT)
, tangani peristiwa itu sendiri, dan tampilkan true
.
Ringkasan
Untuk menangani peristiwa tombol media dengan baik di semua versi Android, Anda harus menentukan FLAG_HANDLES_MEDIA_BUTTONS
saat membuat sesi media.
Selain itu, bergantung pada versi Android yang ingin didukung, Anda juga harus memenuhi persyaratan berikut:
Jika aplikasi berjalan di Android 5.0 atau yang lebih baru:
- Panggil
MediaControllerCompat.setMediaController()
dari callbackonConnected()
pengontrol media - Agar tombol media dapat memulai ulang sesi yang tidak aktif, buatlah
MediaButtonReceiver
secara dinamis dengan memanggilsetMediaButtonReceiver()
dan meneruskanPendingIntent
ke sana
Jika aplikasi berjalan di Android sebelum versi 5.0:
- Ganti
onKeyDown()
aktivitas untuk menangani tombol media - Buat
MediaButtonReceiver
secara statis dengan menambahkannya ke manifes aplikasi