İki veya daha fazla Android uygulaması, sesi aynı çıkış akışına eş zamanlı olarak çalabilir ve sistem her şeyi karıştırır. Bu teknik olarak etkileyici olsa da kullanıcılar için son derece üzücü olabilir. Android, tüm müzik uygulamalarının aynı anda çalmasını önlemek için ses odağı fikrini kullanıma sunar. Aynı anda yalnızca bir uygulama ses odağını tutabilir.
Uygulamanızın ses çıkışını vermesi gerektiğinde sese odaklanmayı istemesi gerekir. Odaklanma olduğunda ses çalabilir. Ancak ses odağını aldıktan sonra, çalana kadar bu sesi tutamayabilirsiniz. Başka bir uygulama odaklanma isteğinde bulunabilir. Bu da sesin odaklanmasını önlüyor. Böyle bir durumda, kullanıcıların yeni ses kaynağını daha kolay duyabilmesi için uygulamanız oynatmayı duraklatmalı veya ses düzeyini düşürmelidir.
Android 12'den (API düzeyi 31) önceki sürümlerde ses odağı sistem tarafından yönetilmez. Bu nedenle, uygulama geliştiricilerin ses odağı yönergelerine uymaları önerilir. Android 11 (API düzeyi 30) veya daha düşük sürümleri çalıştıran bir cihazda ses odağını kaybettikten sonra bile uygulama yüksek sesle çalmaya devam ederse sistem bunu engelleyemez. Ancak bu uygulama davranışı, kötü bir kullanıcı deneyimine yol açar ve çoğu zaman kullanıcıların hatalı çalışan uygulamayı kaldırmasına yol açabilir.
İyi tasarlanmış bir ses uygulaması, ses odağını aşağıdaki genel yönergelere göre yönetmelidir:
Oynamaya başlamadan hemen önce
requestAudioFocus()
numaralı telefonu arayın ve aramanınAUDIOFOCUS_REQUEST_GRANTED
değerini döndürdüğünü doğrulayın. Medya oturumunuzunonPlay()
geri çağırmasındarequestAudioFocus()
çağrısını yapın.Başka bir uygulama sese odaklandığında, çalmayı durdurun veya duraklatın ya da sesi azaltın (yani sesi azaltın).
Oynatma durduğunda (örneğin, uygulamada oynatılacak hiçbir şey kalmadığında) ses odağının kesilmesi. Kullanıcı oynatmayı duraklatır ancak daha sonra devam ettirebilirse uygulamanızın ses odağından vazgeçmesi gerekmez.
Uygulamanızın çaldığı sesin türünü tanımlamak için
AudioAttributes
ifadesini kullanın. Örneğin, konuşma çalan uygulamalar içinCONTENT_TYPE_SPEECH
değerini belirtin.
Ses odağı, çalışan Android sürümüne bağlı olarak farklı şekilde ele alınır:
- Android 12 (API düzeyi 31) veya sonraki sürümler
- Ses odağı sistem tarafından yönetilir. Başka bir uygulama ses odağı isteğinde bulunduğunda sistem, bir uygulamadaki ses çalma işleminin yavaşça kaybolmasını sağlar. Ayrıca, gelen bir arama geldiğinde sistem, çalan sesin sesini kapatır.
- Android 8.0 (API düzeyi 26) ile Android 11 (API düzeyi 30) arası
- Ses odağı, sistem tarafından yönetilmese de Android 8.0 (API düzeyi 26) sürümünden itibaren kullanıma sunulan bazı değişiklikleri içerir.
- Android 7.1 (API düzeyi 25) ve önceki sürümler
- Ses odağı sistem tarafından yönetilmez. Uygulamalar ise ses odağını
requestAudioFocus()
veabandonAudioFocus()
kullanarak yönetir.
Android 12 ve sonraki sürümlerde ses odağı
Ses odağı kullanan bir medya veya oyun uygulaması, odağı kaybolduktan sonra ses çalmamalıdır. Android 12 (API düzeyi 31) ve sonraki sürümlerde sistem bu davranışı uygular. Bir uygulama, odakta ve oyun oynatılırken başka bir uygulama ses odağı istediğinde sistem oynatılan uygulamayı karartmaya zorlar. Şeffaflaştırma efektinin eklenmesi, bir uygulamadan diğerine geçerken daha yumuşak bir geçiş sağlar.
Bu sönme davranışı, aşağıdaki koşullar karşılandığında ortaya çıkar:
Şu anda oynatılan ilk uygulama aşağıdaki kriterlerin tümünü karşılıyor:
- Uygulama
AudioAttributes.USAGE_MEDIA
veyaAudioAttributes.USAGE_GAME
kullanım özelliğine sahip. - Uygulama,
AudioManager.AUDIOFOCUS_GAIN
ile ses odağını başarıyla istedi. - Uygulama,
AudioAttributes.CONTENT_TYPE_SPEECH
içerik türünde ses çalmıyor.
- Uygulama
İkinci bir uygulama
AudioManager.AUDIOFOCUS_GAIN
ile ses odağı istiyor.
Bu koşullar karşılandığında, ses sistemi ilk uygulamadaki sesi yavaşça sona erer. Kaybolmanın sonunda sistem, ilk uygulamaya odak kaybı olduğunu bildirir. Uygulama tekrar ses odağı isteğinde bulunana kadar uygulamanın oynatıcılarının sesi kapalı kalır.
Mevcut ses odağı davranışları
Ses odağında değişiklik yapılmasını gerektiren diğer durumların da farkında olmalısınız.
Otomatik kısma
Android 8.0'da (API düzeyi 26) otomatik sesi kapatma (bir uygulamanın ses düzeyini, diğerinin net bir şekilde duyulması için geçici olarak düşürme) kullanıma sunuldu.
Sistemin içeriği kısmayı uygulamasını sağlayarak uygulamanızda bölmeyi uygulamak zorunda kalmazsınız.
Otomatik kısma, uygulamadaki bir sesli bildirimin odağını çektiğinde de gerçekleşir. Bildirim oynatmanın başlangıcı, ses kısma rampasının sonuyla senkronize edilir.
Otomatik kısma, aşağıdaki koşullar karşılandığında gerçekleşir:
Şu anda oynatılan ilk uygulama aşağıdaki kriterlerin tümünü karşılamaktadır:
- Uygulama her tür odak kazancı ile başarıyla ses odağı istedi.
- Uygulama,
AudioAttributes.CONTENT_TYPE_SPEECH
içerik türüyle ses çalmıyor. - Uygulamada
AudioFocusRequest.Builder.setWillPauseWhenDucked(true)
ayarı yapılmadı.
İkinci bir uygulama ise
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
ile ses odağı istiyor.
Bu koşullar karşılandığında ses sistemi, ilk uygulamadaki tüm etkin oynatıcıları azaltırken ikinci uygulama odaklanır. İkinci uygulama odaklanmayı bıraktığında duyuşturma çözümlenir. İlk uygulama odağını kaybettiğinde bildirim gönderilmediğinden uygulamanın bir şey yapması gerekmez.
Kullanıcı programın bir kısmını atlayabileceğinden, otomatik kısmanın kullanıcı konuşma içeriğini dinlerken gerçekleştirilmediğini unutmayın. Örneğin, arabayla yol tarifleri için sesli yardım boğulmaz.
Gelen telefon aramaları için geçerli ses çalmayı kapat
Bazı uygulamalar düzgün çalışmaz ve telefon aramaları sırasında ses çalmaya devam eder. Bu durum, kullanıcıyı aramayı duymak için rahatsız edici uygulamayı bulup sesini kapatmaya veya kapatmaya zorlar. Sistem bunu önlemek için, gelen bir arama sırasında diğer uygulamaların sesini kapatabilir. Bir gelen telefon araması alındığında ve bir uygulama aşağıdaki koşulları karşıladığında, sistem bu özelliği çağırır:
- Uygulama
AudioAttributes.USAGE_MEDIA
veyaAudioAttributes.USAGE_GAME
kullanım özelliğine sahip. - Uygulama, ses odağını (odak kazanımı) başarıyla istedi ve ses çalıyor.
Arama sırasında bir uygulama çalmaya devam ederse arama sona erene kadar oynatmanın sesi kapatılır. Bununla birlikte, arama sırasında bir uygulama oynamaya başlarsa kullanıcının videoyu bilerek oynatmaya başladığı varsayılarak oynatıcının sesi kapatılmaz.
Android 8.0 ile Android 11 arasındaki sürümlerde ses odağı
Android 8.0 (API düzeyi 26) sürümünden itibaren, requestAudioFocus()
çağrısı yaptığınızda bir AudioFocusRequest
parametresi sağlamanız gerekir. AudioFocusRequest
, uygulamanızın ses bağlamı ve özellikleri hakkında bilgiler içerir. Sistem bu bilgileri, ses odağı kazanımını ve kaybını otomatik olarak yönetmek için kullanır. Ses odağını serbest bırakmak için AudioFocusRequest
bağımsız değişkenini de alan abandonAudioFocusRequest()
yöntemini çağırın. Odaklanma isteğinde bulunurken ve odadan ayrıldığınızda aynı AudioFocusRequest
örneğini kullanın.
AudioFocusRequest
oluşturmak için AudioFocusRequest.Builder
kullanın. Odak isteğinin her zaman istek türünü belirtmesi gerektiğinden tür, oluşturucunun oluşturucusuna eklenir. İsteğin diğer alanlarını ayarlamak için oluşturucunun yöntemlerini kullanın.
FocusGain
alanı zorunludur; diğer tüm alanlar isteğe bağlıdır.
Yöntem | Notlar |
---|---|
setFocusGain()
|
Bu alan her istekte zorunludur. Android 8.0 öncesi requestAudioFocus() çağrısında kullanılan durationHint ile aynı değerleri alır:
AUDIOFOCUS_GAIN , AUDIOFOCUS_GAIN_TRANSIENT ,
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK veya AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE .
|
setAudioAttributes()
|
AudioAttributes , uygulamanızın kullanım alanını açıklar. Sistem, bir uygulama ses odağını kazanıp kaybettiğinde bunları dikkate alır. Özellikler, akış türü kavramının yerini alır. Android 8.0 (API düzeyi 26) ve sonraki sürümlerde ses seviyesi kontrolleri dışındaki işlemler için akış türleri kullanımdan kaldırılmıştır. Odak isteğinde, ses çalarınızda kullandığınız özelliklerin aynılarını kullanın (bu tabloyu aşağıdaki örnekte gösterildiği gibi).
Önce özellikleri belirtmek için bir
Belirtilmezse |
setWillPauseWhenDucked()
|
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK ile odaklanmayı sağlayan başka bir uygulama istediğinde, sistem bunu kendi başına yapabilir. Bu nedenle, odaklanan uygulama genellikle onAudioFocusChange() geri çağırma yapmaz. Sesi kısmak yerine çalmayı duraklatmanız gerektiğinde setWillPauseWhenDucked(true) öğesini arayın ve otomatik kısma bölümünde açıklandığı gibi bir OnAudioFocusChangeListener oluşturup ayarlayın.
|
setAcceptsDelayedFocusGain()
|
Odak başka bir uygulama tarafından kilitlendiğinde, bir ses odaklama isteği başarısız olabilir.
Bu yöntem, gecikmeli odaklanma kazancını, yani kullanılabilir olduğunda
odağı eşzamansız olarak elde etme olanağı sağlar.
Uygulamanızın odağın verildiğini anlayabilmesi için geri çağırmayı alması gerektiğinden, gecikmeli odak kazancı yalnızca ses isteğinde bir |
setOnAudioFocusChangeListener()
|
OnAudioFocusChangeListener , yalnızca istekte willPauseWhenDucked(true) veya setAcceptsDelayedFocusGain(true) belirtmeniz durumunda gereklidir.
İşleyiciyi ayarlamanın iki yöntemi vardır: işleyici bağımsız değişkeni olan ve olmayan iki yöntem. İşleyici, işleyicinin üzerinde çalıştığı iş parçacığıdır. İşleyici belirtmezseniz ana |
Aşağıdaki örnekte, AudioFocusRequest
oluşturmak ve ses odağını istemek ve terk etmek için AudioFocusRequest.Builder
öğesinin nasıl kullanılacağı gösterilmektedir:
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; } } }
Otomatik kısma
Android 8.0'da (API düzeyi 26), başka bir uygulama AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
ile odaklanma isteğinde bulunduğunda sistem, uygulamanın onAudioFocusChange()
geri çağırmasını çağırmadan sesi azaltıp geri yükleyebilir.
Otomatik kısma, müzik ve video oynatma uygulamalarında kabul edilebilir bir davranış olsa da, sesli kitap uygulamaları gibi sözlü içerik oynatıldığında faydalı değildir. Bu durumda uygulamanın duraklatılması gerekir.
Uygulamanızın sesini kısmak yerine kısması istendiğinde duraklatılmasını istiyorsanız istenen duraklatma/devam ettirme davranışını uygulayan onAudioFocusChange()
geri çağırma yöntemine sahip bir OnAudioFocusChangeListener
oluşturun.
Dinleyiciyi kaydetmek için setOnAudioFocusChangeListener()
numaralı telefonu arayın ve sisteme, otomatik kısma işlemi yapmak yerine geri aramanızı kullanmasını söylemek için setWillPauseWhenDucked(true)
numaralı telefonu arayın.
Gecikmeli odak kazancı
Bazen odak başka bir uygulama tarafından "kilitlendiğinde" (ör. telefon araması sırasında) sistem, ses odaklanması için bir isteği kabul edemez. Bu durumda requestAudioFocus()
, AUDIOFOCUS_REQUEST_FAILED
değerini döndürür. Böyle bir durumda
uygulamanız odaklanmadığı için
sesli çalma işlemine devam etmemelidir.
Uygulamanızın odaklanma isteğini eşzamansız olarak işlemesini sağlayan setAcceptsDelayedFocusGain(true)
yöntemi. Bu işaret ayarlandığında, odak kilitliyken yapılan bir istek AUDIOFOCUS_REQUEST_DELAYED
değerini döndürür. Ses odağını kilitleyen koşul artık mevcut olmadığında (ör. bir telefon aramasının sona ermesi durumunda) sistem bekleyen odaklanma isteğini kabul eder ve onAudioFocusChange()
çağırarak uygulamanızı bildirir.
Odaklanmanın gecikmeli kazanımını yönetmek için istenen davranışı uygulayan onAudioFocusChange()
geri çağırma yöntemine sahip bir OnAudioFocusChangeListener
oluşturmanız ve setOnAudioFocusChangeListener()
çağrısı yaparak işleyiciyi kaydetmeniz gerekir.
Android 7.1 ve önceki sürümlerde ses odağı
requestAudioFocus()
çağrısı yaptığınızda, o anda odağı tutan ve oynatılan başka bir uygulama tarafından geçerli olabilecek bir süre ipucu belirtmeniz gerekir:
- Öngörülebilir gelecekte ses çalmayı planlıyorsanız (örneğin, müzik çalarken) ve ses odağının önceki sahibinin çalmayı durdurmasını bekliyorsanız kalıcı ses odağı (
AUDIOFOCUS_GAIN
) isteyin. - Sesin yalnızca kısa bir süreliğine çalınmasını ve önceki kullanıcının çalmayı duraklatmasını beklediğiniz durumlarda geçici odak (
AUDIOFOCUS_GAIN_TRANSIENT
) isteğinde bulunun. - Sesin yalnızca kısa bir süre için çalınmasını beklediğinizi ve ses çıkışını "kıstığı" (kısıtlıyorsa) önceki odak sahibinin içeriği oynatmaya devam edebileceğini belirtmek için bırakma (
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
) ile geçici odaklanma isteğinde bulunun. Her iki ses çıkışı da ses akışına karıştırılır. Sesi kısma özelliği, özellikle ses akışını kesintili olarak kullanan uygulamalar (ör. sesli arabayla yol tarifleri) için uygundur.
requestAudioFocus()
yöntemi için AudioManager.OnAudioFocusChangeListener
de gerekir. Bu işleyici, medya oturumunuzun sahibi olan etkinlik veya hizmette oluşturulmalıdır. Bu model, başka bir uygulama ses odağını elde ettiğinde veya terk ettiğinde uygulamanızın aldığı onAudioFocusChange()
geri çağırmasını uygular.
Aşağıdaki snippet, STREAM_MUSIC
akışına kalıcı bir ses odağı ister ve ses odağında sonraki değişiklikleri işlemek için bir OnAudioFocusChangeListener
kaydeder. (Değişiklik dinleyicisi, Ses odağı değişikliğine yanıt verme bölümünde ele alınmıştır.)
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 }
Oynatmayı tamamladığınızda abandonAudioFocus()
numaralı telefonu arayın.
Kotlin
audioManager.abandonAudioFocus(afChangeListener)
Java
// Abandon audio focus when playback complete audioManager.abandonAudioFocus(afChangeListener);
Bu işlem, sisteme artık odaklanmanızın gerekli olmadığını bildirir ve ilişkilendirilmiş OnAudioFocusChangeListener
öğesinin kaydını iptal eder. Geçici odaklama isteğinde bulunduysanız bu işlem, duraklatan veya kısılmış bir uygulamaya ses çalmaya devam edebileceğini ya da sesini geri yükleyebileceğini bildirir.
Ses odağı değişikliğine yanıt verme
Bir uygulama ses odağı elde ettiğinde, başka bir uygulama kendisi için ses odağı isteğinde bulunduğunda bu uygulamayı serbest bırakabilmelidir. Bu durumda uygulamanız, requestAudioFocus()
adlı uygulamayı çağırırken belirttiğiniz AudioFocusChangeListener
öğesindeki onAudioFocusChange()
yöntemine çağrı alır.
onAudioFocusChange()
öğesine iletilen focusChange
parametresi, gerçekleşen değişikliğin türünü belirtir. Odaklanmayı sağlayan uygulama tarafından kullanılan süre ipucuna karşılık gelir. Uygulamanız da
uygun şekilde yanıt vermelidir.
- Geçici odak kaybı
-
Odak değişikliği geçiciyse (
AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK
veyaAUDIOFOCUS_LOSS_TRANSIENT
) uygulamanızın eğilmesi (otomatik kısma kullanmıyorsanız) ya da oynamayı duraklatması ancak aksi takdirde aynı durumu koruması gerekir.Ses odağının geçici olarak kaybolması sırasında ses odağındaki değişiklikleri izlemeye devam etmeli ve yeniden odaklandığınızda normal oynatmaya devam etmeye hazır olmalısınız. Engelleme uygulaması odaklanmayı bıraktığında geri arama (
AUDIOFOCUS_GAIN
) alırsınız. Bu noktada ses düzeyini normal seviyesine geri getirebilir veya oynatmayı yeniden başlatabilirsiniz. - Kalıcı odak kaybı
-
Ses odağı kaybı kalıcısa (
AUDIOFOCUS_LOSS
) başka bir uygulama ses çalıyordur. Uygulamanız, hiçbir zamanAUDIOFOCUS_GAIN
araması almayacağı için oynatmayı hemen duraklatmalıdır. Oynatmayı yeniden başlatmak için kullanıcının, bildirim veya uygulama kullanıcı arayüzündeki oynat aktarma kontrolüne basmak gibi açık bir işlem yapması gerekir.
Aşağıdaki kod snippet'inde, OnAudioFocusChangeListener
ve onAudioFocusChange()
geri çağırmasının nasıl uygulanacağı gösterilmektedir. Ses odağının kalıcı olarak kaybolması durumunda geri çağırmayı ertelemek için Handler
kullanıldığına dikkat edin.
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 } } };
İşleyici şuna benzeyen bir Runnable
kullanır:
Kotlin
private var delayedStopRunnable = Runnable { mediaController.transportControls.stop() }
Java
private Runnable delayedStopRunnable = new Runnable() { @Override public void run() { getMediaController().getTransportControls().stop(); } };
Kullanıcı oynatmayı yeniden başlatırsa gecikmeli durdurmanın devreye girmemesi için durum değişikliklerine yanıt olarak mHandler.removeCallbacks(mDelayedStopRunnable)
yöntemini çağırın. Örneğin, Geri Arama'nın onPlay()
,
onSkipToNext()
vb. öğelerinde removeCallbacks()
yöntemini çağırın. Hizmetiniz tarafından kullanılan kaynakları temizlerken hizmetinizin onDestroy()
geri çağırmasında da bu yöntemi çağırmalısınız.