Dua atau beberapa aplikasi Android dapat memutar audio ke aliran output yang sama secara bersamaan, dan sistem akan menggabungkan semuanya. Meskipun secara teknis mengesankan, hal ini dapat sangat mengganggu pengguna. Untuk menghindari setiap aplikasi musik diputar secara bersamaan, Android memperkenalkan ide fokus audio. Hanya satu aplikasi yang dapat menerima fokus audio pada satu waktu.
Saat perlu meng-output audio, aplikasi Anda harus meminta fokus audio. Saat memiliki fokus, aplikasi dapat memutar suara. Namun, setelah mendapatkan fokus audio, Anda mungkin tidak dapat mempertahankannya hingga selesai memutar. Aplikasi lain dapat meminta fokus, yang mendahului penahanan Anda pada fokus audio. Jika hal itu terjadi, aplikasi Anda harus menjeda pemutaran atau menurunkan volumenya agar pengguna dapat mendengar sumber audio baru dengan lebih mudah.
Sebelum Android 12 (API level 31), fokus audio tidak dikelola oleh sistem. Jadi, meskipun developer aplikasi dianjurkan untuk mematuhi pedoman fokus audio, jika aplikasi terus memutar audio dengan keras bahkan setelah kehilangan fokus audio di perangkat yang menjalankan Android 11 (API level 30) atau yang lebih rendah, sistem tidak dapat mencegahnya. Namun, perilaku aplikasi ini menyebabkan pengalaman pengguna yang buruk dan sering kali dapat menyebabkan pengguna meng-uninstal aplikasi yang berperilaku buruk.
Aplikasi audio yang dirancang dengan baik harus mengelola fokus audio sesuai dengan panduan umum berikut:
Panggil
requestAudioFocus()segera sebelum mulai memutar dan pastikan panggilan menampilkanAUDIOFOCUS_REQUEST_GRANTED. Lakukan panggilan kerequestAudioFocus()di callbackonPlay()sesi media Anda.Saat aplikasi lain mendapatkan fokus audio, hentikan atau jeda pemutaran, atau kecilkan (yaitu, kurangi) volume.
Saat pemutaran berhenti (misalnya, saat aplikasi tidak memiliki apa pun lagi untuk diputar), lepaskan fokus audio. Aplikasi Anda tidak harus mengabaikan fokus audio jika pengguna menjeda pemutaran, tetapi mungkin akan melanjutkan pemutaran nanti.
Gunakan
AudioAttributesuntuk mendeskripsikan jenis audio yang diputar aplikasi Anda. Misalnya, untuk aplikasi yang memutar ucapan, tentukanCONTENT_TYPE_SPEECH.
Fokus audio ditangani secara berbeda bergantung pada versi Android yang berjalan:
- Android 12 (level API 31) atau yang lebih baru
- Fokus audio dikelola oleh sistem. Sistem memaksa pemutaran audio dari sebuah aplikasi untuk memudar saat aplikasi lain meminta fokus audio. Sistem juga akan membisukan pemutaran audio saat ada panggilan masuk.
- Android 8.0 (level API 26) hingga Android 11 (level API 30)
- Fokus audio tidak dikelola oleh sistem, tetapi menyertakan beberapa perubahan yang diperkenalkan mulai Android 8.0 (level API 26).
- Android 7.1 (level API 25) dan yang lebih rendah
- Fokus audio tidak dikelola oleh sistem, dan aplikasi mengelola fokus audio menggunakan
requestAudioFocus()danabandonAudioFocus().
Fokus audio di Android 12 dan yang lebih baru
Aplikasi media atau game yang menggunakan fokus audio seharusnya tidak memutar audio setelah kehilangan fokus. Di Android 12 (API level 31) dan yang lebih tinggi, sistem menerapkan perilaku ini. Saat aplikasi meminta fokus audio sementara aplikasi lain memiliki fokus dan sedang diputar, sistem akan memaksa aplikasi yang sedang diputar untuk memudar. Penambahan fade-out memberikan transisi yang lebih halus saat berpindah dari satu aplikasi ke aplikasi lainnya.
Perilaku fade out ini terjadi jika kondisi berikut terpenuhi:
Aplikasi pertama yang sedang diputar memenuhi semua kriteria berikut:
- Aplikasi memiliki atribut penggunaan
AudioAttributes.USAGE_MEDIAatauAudioAttributes.USAGE_GAME. - Aplikasi berhasil meminta fokus audio dengan
AudioManager.AUDIOFOCUS_GAIN. - Aplikasi tidak memutar audio dengan jenis konten
AudioAttributes.CONTENT_TYPE_SPEECH.
- Aplikasi memiliki atribut penggunaan
Aplikasi kedua meminta fokus audio dengan
AudioManager.AUDIOFOCUS_GAIN.
Jika kondisi ini terpenuhi, sistem audio akan memudarkan aplikasi pertama. Di akhir pemudaran, sistem akan memberi tahu aplikasi pertama tentang hilangnya fokus. Pemutar aplikasi tetap dibisukan hingga aplikasi meminta fokus audio lagi.
Perilaku fokus audio yang ada
Anda juga harus mengetahui kasus lain yang melibatkan pengalihan fokus audio.
Pengecilan volume otomatis
Pengecilan volume otomatis (mengurangi level audio satu aplikasi untuk sementara agar aplikasi lain dapat didengar dengan jelas) diperkenalkan di Android 8.0 (API level 26).
Dengan meminta sistem menerapkan ducking, Anda tidak perlu menerapkan ducking di aplikasi Anda.
Pengecilan volume otomatis juga terjadi saat notifikasi audio mengambil fokus dari aplikasi yang sedang diputar. Awal pemutaran notifikasi disinkronkan dengan pengoptimalan penurunan volume.
Pengecilan volume otomatis terjadi jika kondisi berikut terpenuhi:
Aplikasi pertama yang sedang diputar memenuhi semua kriteria berikut:
- Aplikasi berhasil meminta fokus audio dengan jenis perolehan fokus apa pun.
- Aplikasi tidak memutar audio dengan jenis konten
AudioAttributes.CONTENT_TYPE_SPEECH. - Aplikasi tidak menetapkan
AudioFocusRequest.Builder.setWillPauseWhenDucked(true).
Aplikasi kedua meminta fokus audio dengan
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK.
Jika kondisi ini terpenuhi, sistem audio akan mengecilkan volume semua pemutar aktif aplikasi pertama saat aplikasi kedua memiliki fokus. Saat aplikasi kedua mengabaikan fokus, aplikasi tersebut akan membatalkan pengecilan volume. Aplikasi pertama tidak diberi tahu saat kehilangan fokus, sehingga tidak perlu melakukan apa pun.
Perhatikan bahwa ducking otomatis tidak dilakukan saat pengguna mendengarkan konten ucapan, karena pengguna mungkin melewatkan beberapa program. Misalnya, panduan suara untuk rute mobil tidak dikecilkan.
Membisukan pemutaran audio saat ini untuk panggilan telepon masuk
Beberapa aplikasi tidak berfungsi dengan baik dan terus memutar audio selama panggilan telepon. Situasi ini memaksa pengguna untuk menemukan dan membisukan atau keluar dari aplikasi yang mengganggu agar dapat mendengar panggilan mereka. Untuk mencegah hal ini, sistem dapat membisukan audio dari aplikasi lain saat ada panggilan masuk. Sistem akan memanggil fitur ini saat panggilan telepon masuk diterima dan aplikasi memenuhi kondisi berikut:
- Aplikasi memiliki atribut penggunaan
AudioAttributes.USAGE_MEDIAatauAudioAttributes.USAGE_GAME. - Aplikasi berhasil meminta fokus audio (perolehan fokus apa pun) dan memutar audio.
Jika aplikasi terus diputar selama panggilan, pemutarannya akan dibisukan hingga panggilan berakhir. Namun, jika aplikasi mulai diputar selama panggilan, pemutar tersebut tidak akan dibisukan dengan asumsi bahwa pengguna memulai pemutaran dengan sengaja.
Fokus audio di Android 8.0 hingga Android 11
Mulai Android 8.0 (level API 26), saat memanggil
requestAudioFocus(),
Anda harus menyediakan parameter AudioFocusRequest. AudioFocusRequest
berisi informasi tentang konteks audio dan kemampuan aplikasi Anda. Sistem
menggunakan informasi ini untuk mengelola perolehan dan kehilangan fokus audio
secara otomatis. Untuk melepaskan fokus audio, panggil metode
abandonAudioFocusRequest()
yang juga menggunakan AudioFocusRequest sebagai argumennya. Gunakan instance
AudioFocusRequest yang sama saat Anda meminta dan mengabaikan fokus.
Untuk membuat AudioFocusRequest, gunakan
AudioFocusRequest.Builder. Karena permintaan fokus harus
selalu menentukan jenis permintaan, jenis tersebut disertakan dalam konstruktor
untuk builder. Gunakan metode builder untuk menetapkan kolom permintaan lainnya.
Kolom FocusGain wajib diisi; semua kolom lainnya bersifat opsional.
| Metode | Catatan |
|---|---|
setFocusGain()
|
Kolom ini wajib diisi dalam setiap permintaan. Nilainya sama dengan
durationHint yang digunakan dalam panggilan pra-Android 8.0 ke requestAudioFocus():
AUDIOFOCUS_GAIN, AUDIOFOCUS_GAIN_TRANSIENT,
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, atau AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE.
|
setAudioAttributes()
|
AudioAttributes menjelaskan kasus penggunaan untuk aplikasi Anda. Sistem akan melihatnya saat aplikasi mendapatkan dan kehilangan fokus audio. Atribut
menggantikan konsep jenis streaming. Di Android 8.0 (level API 26) dan yang lebih baru, jenis streaming untuk operasi apa pun selain kontrol volume tidak digunakan lagi. Gunakan
atribut yang sama dalam permintaan fokus yang Anda gunakan di pemutar audio (seperti
yang ditunjukkan dalam contoh setelah tabel ini).
Gunakan
Jika tidak ditentukan, |
setWillPauseWhenDucked()
|
Saat aplikasi lain meminta fokus dengan
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, aplikasi yang memiliki fokus biasanya tidak
menerima callback
onAudioFocusChange()
karena sistem dapat melakukan
ducking sendiri. Jika Anda perlu menjeda pemutaran, bukan
mengecilkan volume, panggil setWillPauseWhenDucked(true), lalu buat dan tetapkan
OnAudioFocusChangeListener, seperti yang dijelaskan dalam pengecilan
otomatis.
|
setAcceptsDelayedFocusGain()
|
Permintaan fokus audio dapat gagal jika fokus dikunci oleh aplikasi lain.
Metode ini memungkinkan perolehan fokus yang tertunda: kemampuan
untuk memperoleh fokus secara asinkron saat tersedia.
Perhatikan bahwa penundaan perolehan fokus hanya berfungsi jika Anda juga menentukan
|
setOnAudioFocusChangeListener()
|
OnAudioFocusChangeListener hanya diperlukan jika Anda juga menentukan
willPauseWhenDucked(true) atau setAcceptsDelayedFocusGain(true) dalam permintaan.
Ada dua metode untuk menetapkan pemroses: satu dengan dan satu tanpa argumen pengendali. Pengendali ini adalah thread tempat pemroses berjalan. Jika Anda
tidak menentukan pengendali, pengendali yang terkait dengan
|
Contoh berikut menunjukkan cara menggunakan AudioFocusRequest.Builder untuk membuat
AudioFocusRequest serta meminta dan mengabaikan fokus audio:
Kotlin
// initializing variables for audio focus and playback management audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager focusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN).run { setAudioAttributes(AudioAttributes.Builder().run { setUsage(AudioAttributes.USAGE_GAME) setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) build() }) setAcceptsDelayedFocusGain(true) setOnAudioFocusChangeListener(afChangeListener, handler) build() } val focusLock = Any() var playbackDelayed = false var playbackNowAuthorized = false // requesting audio focus and processing the response val res = audioManager.requestAudioFocus(focusRequest) synchronized(focusLock) { playbackNowAuthorized = when (res) { AudioManager.AUDIOFOCUS_REQUEST_FAILED -> false AudioManager.AUDIOFOCUS_REQUEST_GRANTED -> { playbackNow() true } AudioManager.AUDIOFOCUS_REQUEST_DELAYED -> { playbackDelayed = true false } else -> false } } // implementing OnAudioFocusChangeListener to react to focus changes override fun onAudioFocusChange(focusChange: Int) { when (focusChange) { AudioManager.AUDIOFOCUS_GAIN -> if (playbackDelayed || resumeOnFocusGain) { synchronized(focusLock) { playbackDelayed = false resumeOnFocusGain = false } playbackNow() } AudioManager.AUDIOFOCUS_LOSS -> { synchronized(focusLock) { resumeOnFocusGain = false playbackDelayed = false } pausePlayback() } AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> { synchronized(focusLock) { // only resume if playback is being interrupted resumeOnFocusGain = isPlaying() playbackDelayed = false } pausePlayback() } AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> { // ... pausing or ducking depends on your app } } }
Java
// initializing variables for audio focus and playback management audioManager = (AudioManager) Context.getSystemService(Context.AUDIO_SERVICE); playbackAttributes = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_GAME) .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .build(); focusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN) .setAudioAttributes(playbackAttributes) .setAcceptsDelayedFocusGain(true) .setOnAudioFocusChangeListener(afChangeListener, handler) .build(); final Object focusLock = new Object(); boolean playbackDelayed = false; boolean playbackNowAuthorized = false; // requesting audio focus and processing the response int res = audioManager.requestAudioFocus(focusRequest); synchronized(focusLock) { if (res == AudioManager.AUDIOFOCUS_REQUEST_FAILED) { playbackNowAuthorized = false; } else if (res == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { playbackNowAuthorized = true; playbackNow(); } else if (res == AudioManager.AUDIOFOCUS_REQUEST_DELAYED) { playbackDelayed = true; playbackNowAuthorized = false; } } // implementing OnAudioFocusChangeListener to react to focus changes @Override public void onAudioFocusChange(int focusChange) { switch (focusChange) { case AudioManager.AUDIOFOCUS_GAIN: if (playbackDelayed || resumeOnFocusGain) { synchronized(focusLock) { playbackDelayed = false; resumeOnFocusGain = false; } playbackNow(); } break; case AudioManager.AUDIOFOCUS_LOSS: synchronized(focusLock) { resumeOnFocusGain = false; playbackDelayed = false; } pausePlayback(); break; case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: synchronized(focusLock) { // only resume if playback is being interrupted resumeOnFocusGain = isPlaying(); playbackDelayed = false; } pausePlayback(); break; case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: // ... pausing or ducking depends on your app break; } } }
Pengecilan volume otomatis
Di Android 8.0 (API level 26), saat aplikasi lain meminta fokus dengan
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, sistem dapat mengecilkan dan memulihkan volume
tanpa memanggil callback onAudioFocusChange() aplikasi.
Meskipun penghentian sementara otomatis adalah perilaku yang dapat diterima untuk aplikasi pemutaran musik dan video, hal ini tidak berguna saat memutar konten lisan, seperti dalam aplikasi buku audio. Dalam hal ini, aplikasi harus dijeda.
Jika Anda ingin aplikasi dijeda saat diminta untuk mengecilkan volume, buat OnAudioFocusChangeListener dengan
metode callback onAudioFocusChange() yang mengimplementasikan perilaku jeda/lanjutkan yang diinginkan.
Panggil setOnAudioFocusChangeListener() untuk mendaftarkan pemroses, dan panggil
setWillPauseWhenDucked(true)
untuk memberi tahu sistem agar menggunakan callback Anda, bukan melakukan ducking otomatis.
Perolehan fokus tertunda
Terkadang sistem tidak dapat mengabulkan permintaan fokus audio karena fokus
"dikunci" oleh aplikasi lain, seperti selama panggilan telepon. Dalam hal ini,
requestAudioFocus() menampilkan AUDIOFOCUS_REQUEST_FAILED. Jika hal ini terjadi,
aplikasi Anda tidak boleh melanjutkan pemutaran audio karena tidak mendapatkan
fokus.
Metode, setAcceptsDelayedFocusGain(true), yang memungkinkan aplikasi Anda menangani permintaan fokus
secara asinkron. Dengan flag ini ditetapkan, permintaan yang dibuat saat fokus dikunci akan menampilkan AUDIOFOCUS_REQUEST_DELAYED. Jika kondisi yang mengunci fokus audio
tidak ada lagi, seperti saat panggilan telepon berakhir, sistem
akan mengabulkan permintaan fokus yang tertunda dan memanggil onAudioFocusChange() untuk memberi tahu
aplikasi Anda.
Untuk menangani perolehan fokus yang tertunda, Anda harus membuat
OnAudioFocusChangeListener dengan metode callback onAudioFocusChange() yang
mengimplementasikan perilaku yang diinginkan dan mendaftarkan pemroses dengan memanggil
setOnAudioFocusChangeListener().
Fokus audio di Android 7.1 dan yang lebih lama
Saat memanggil
requestAudioFocus(),
Anda harus menentukan petunjuk durasi, yang mungkin
dihormati oleh aplikasi lain yang saat ini memegang fokus dan sedang diputar:
- Minta fokus audio permanen (
AUDIOFOCUS_GAIN) saat Anda berencana memutar audio dalam waktu dekat (misalnya, saat memutar musik) dan Anda mengharapkan pemegang fokus audio sebelumnya berhenti memutar. - Minta fokus sementara (
AUDIOFOCUS_GAIN_TRANSIENT) jika Anda ingin memutar audio hanya dalam waktu singkat dan Anda ingin pemegang sebelumnya menjeda pemutaran. - Minta fokus sementara dengan ducking
(
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK) untuk menunjukkan bahwa Anda ingin memutar audio hanya dalam waktu singkat dan pemilik fokus sebelumnya boleh terus memutar jika "ducking" (menurunkan) output audionya. Kedua output audio digabungkan ke dalam streaming audio. Pengecilan volume sangat cocok untuk aplikasi yang menggunakan streaming audio sesekali, seperti untuk rute mobil yang terdengar.
Metode requestAudioFocus() juga memerlukan AudioManager.OnAudioFocusChangeListener. Pemroses ini harus
dibuat dalam aktivitas atau layanan yang sama dengan yang memiliki sesi media Anda. Class ini
mengimplementasikan callback onAudioFocusChange() yang diterima aplikasi Anda saat
aplikasi lain memperoleh atau melepaskan fokus audio.
Cuplikan berikut meminta fokus audio permanen pada streaming
STREAM_MUSIC dan mendaftarkan OnAudioFocusChangeListener untuk menangani
perubahan berikutnya dalam fokus audio. (Pemroses perubahan dibahas dalam
Merespons perubahan fokus audio.)
Kotlin
audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager lateinit var afChangeListener AudioManager.OnAudioFocusChangeListener ... // Request audio focus for playback val result: Int = audioManager.requestAudioFocus( afChangeListener, // Use the music stream. AudioManager.STREAM_MUSIC, // Request permanent focus. AudioManager.AUDIOFOCUS_GAIN ) if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { // Start playback }
Java
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); AudioManager.OnAudioFocusChangeListener afChangeListener; ... // Request audio focus for playback int result = audioManager.requestAudioFocus(afChangeListener, // Use the music stream. AudioManager.STREAM_MUSIC, // Request permanent focus. AudioManager.AUDIOFOCUS_GAIN); if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { // Start playback }
Setelah Anda selesai memutar, panggil
abandonAudioFocus().
Kotlin
audioManager.abandonAudioFocus(afChangeListener)
Java
// Abandon audio focus when playback complete audioManager.abandonAudioFocus(afChangeListener);
Tindakan ini akan memberi tahu sistem bahwa Anda tidak lagi memerlukan fokus dan membatalkan pendaftaran
OnAudioFocusChangeListener terkait. Jika Anda meminta fokus sementara,
tindakan ini akan memberi tahu aplikasi yang dijeda atau dikecilkan volumenya bahwa aplikasi tersebut dapat melanjutkan pemutaran atau
memulihkan volumenya.
Merespons perubahan fokus audio
Saat memperoleh fokus audio, aplikasi harus dapat melepaskannya saat aplikasi lain
meminta fokus audio untuk dirinya sendiri. Jika hal ini terjadi, aplikasi Anda
akan menerima panggilan ke
metode
onAudioFocusChange()
di AudioFocusChangeListener
yang Anda tentukan saat aplikasi memanggil requestAudioFocus().
Parameter focusChange yang diteruskan ke onAudioFocusChange() menunjukkan jenis
perubahan yang terjadi. Hal ini sesuai
dengan petunjuk durasi yang digunakan oleh aplikasi yang memperoleh fokus. Aplikasi Anda harus
merespons dengan tepat.
- Kehilangan fokus sementara
-
Jika perubahan fokus bersifat sementara (
AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCKatauAUDIOFOCUS_LOSS_TRANSIENT), aplikasi Anda harus mengecilkan volume (jika Anda tidak mengandalkan pengecilan volume otomatis) atau menjeda pemutaran, tetapi tetap mempertahankan status yang sama.Selama kehilangan fokus audio sementara, Anda harus terus memantau perubahan pada fokus audio dan bersiap untuk melanjutkan pemutaran normal saat mendapatkan kembali fokus. Saat aplikasi yang memblokir melepaskan fokus, Anda akan menerima callback (
AUDIOFOCUS_GAIN). Pada tahap ini, Anda dapat memulihkan volume ke tingkat normal atau memulai ulang pemutaran. - Kehilangan fokus permanen
-
Jika kehilangan fokus audio bersifat permanen (
AUDIOFOCUS_LOSS), aplikasi lain sedang memutar audio. Aplikasi Anda harus segera menjeda pemutaran, karena tidak akan pernah menerima callbackAUDIOFOCUS_GAIN. Untuk memulai ulang pemutaran, pengguna harus melakukan tindakan eksplisit, seperti menekan kontrol pemutaran di notifikasi atau UI aplikasi.
Cuplikan kode berikut menunjukkan cara mengimplementasikan
OnAudioFocusChangeListener dan callback onAudioFocusChange()-nya. Perhatikan
penggunaan Handler untuk menunda callback berhenti pada kehilangan fokus audio
permanen.
Kotlin
private val handler = Handler() private val afChangeListener = AudioManager.OnAudioFocusChangeListener { focusChange -> when (focusChange) { AudioManager.AUDIOFOCUS_LOSS -> { // Permanent loss of audio focus // Pause playback immediately mediaController.transportControls.pause() // Wait 30 seconds before stopping playback handler.postDelayed(delayedStopRunnable, TimeUnit.SECONDS.toMillis(30)) } AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> { // Pause playback } AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> { // Lower the volume, keep playing } AudioManager.AUDIOFOCUS_GAIN -> { // Your app has been granted audio focus again // Raise volume to normal, restart playback if necessary } } }
Java
private Handler handler = new Handler(); AudioManager.OnAudioFocusChangeListener afChangeListener = new AudioManager.OnAudioFocusChangeListener() { public void onAudioFocusChange(int focusChange) { if (focusChange == AudioManager.AUDIOFOCUS_LOSS) { // Permanent loss of audio focus // Pause playback immediately mediaController.getTransportControls().pause(); // Wait 30 seconds before stopping playback handler.postDelayed(delayedStopRunnable, TimeUnit.SECONDS.toMillis(30)); } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) { // Pause playback } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) { // Lower the volume, keep playing } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) { // Your app has been granted audio focus again // Raise volume to normal, restart playback if necessary } } };
Pengendali menggunakan Runnable yang terlihat seperti ini:
Kotlin
private var delayedStopRunnable = Runnable { mediaController.transportControls.stop() }
Java
private Runnable delayedStopRunnable = new Runnable() { @Override public void run() { getMediaController().getTransportControls().stop(); } };
Untuk memastikan penghentian yang tertunda tidak terjadi jika pengguna memulai ulang pemutaran, panggil
mHandler.removeCallbacks(mDelayedStopRunnable) sebagai respons terhadap perubahan
status apa pun. Misalnya, panggil removeCallbacks() di onPlay(), onSkipToNext(), dll. Callback Anda. Anda juga harus memanggil metode ini di callback onDestroy() layanan Anda saat membersihkan resource yang digunakan oleh layanan Anda.