दो या उससे ज़्यादा Android ऐप्लिकेशन, एक ही आउटपुट स्ट्रीम पर एक साथ ऑडियो चला सकते हैं. साथ ही, सिस्टम सभी ऑडियो को एक साथ चलाता है. हालांकि, यह तकनीकी रूप से बेहतर है, लेकिन इससे उपयोगकर्ता को बहुत परेशानी हो सकती है. Android ने ऑडियो फ़ोकस की सुविधा लॉन्च की है. इससे, एक साथ कई संगीत ऐप्लिकेशन चलने से रोका जा सकता है. एक बार में सिर्फ़ एक ऐप्लिकेशन ऑडियो फ़ोकस रख सकता है.
जब आपके ऐप्लिकेशन को ऑडियो आउटपुट करने की ज़रूरत होती है, तो उसे ऑडियो फ़ोकस का अनुरोध करना चाहिए. फ़ोकस होने पर, यह आवाज़ चला सकता है. हालांकि, ऑडियो फ़ोकस पाने के बाद, हो सकता है कि आपके पास उसे तब तक रखने का विकल्प न हो, जब तक कि गेम खत्म न हो जाए. कोई दूसरा ऐप्लिकेशन, ऑडियो फ़ोकस का अनुरोध कर सकता है. इससे, ऑडियो फ़ोकस पर आपका कंट्रोल हट जाता है. ऐसा होने पर, आपके ऐप्लिकेशन को ऑडियो चलाना रोकना चाहिए या उसकी आवाज़ कम करनी चाहिए, ताकि उपयोगकर्ता नए ऑडियो सोर्स को आसानी से सुन सकें.
Android 12 (एपीआई लेवल 31) से पहले, ऑडियो फ़ोकस को सिस्टम मैनेज नहीं करता था. इसलिए, ऐप्लिकेशन डेवलपर को ऑडियो फ़ोकस के दिशा-निर्देशों का पालन करने के लिए कहा जाता है. हालांकि, अगर Android 11 (एपीआई लेवल 30) या उससे पहले के वर्शन पर चलने वाले डिवाइस पर, ऑडियो फ़ोकस हटने के बाद भी कोई ऐप्लिकेशन तेज़ आवाज़ में चलता रहता है, तो सिस्टम उसे रोक नहीं सकता. हालांकि, ऐप्लिकेशन के इस व्यवहार से उपयोगकर्ता अनुभव खराब होता है. साथ ही, अक्सर उपयोगकर्ता ऐसे ऐप्लिकेशन को अनइंस्टॉल कर देते हैं जो ठीक से काम नहीं करता.
अच्छी तरह से डिज़ाइन किए गए ऑडियो ऐप्लिकेशन को, ऑडियो फ़ोकस को इन सामान्य दिशा-निर्देशों के मुताबिक मैनेज करना चाहिए:
गेम खेलना शुरू करने से ठीक पहले
requestAudioFocus()
पर कॉल करें और पुष्टि करें कि कॉल परAUDIOFOCUS_REQUEST_GRANTED
दिख रहा है. अपने मीडिया सेशन केonPlay()
कॉलबैक में,requestAudioFocus()
को कॉल करें.जब कोई दूसरा ऐप्लिकेशन ऑडियो फ़ोकस हासिल करता है, तो ऑडियो चलाना बंद करें या उसे रोकें या आवाज़ कम करें.
जब वीडियो चलाना बंद हो जाए (उदाहरण के लिए, जब ऐप्लिकेशन में कोई वीडियो न बचे), तो ऑडियो फ़ोकस बंद कर दें. अगर उपयोगकर्ता ने वीडियो चलाना रोक दिया है, लेकिन हो सकता है कि वह बाद में वीडियो चलाना फिर से शुरू करे, तो आपके ऐप्लिकेशन को ऑडियो फ़ोकस छोड़ने की ज़रूरत नहीं है.
AudioAttributes
का इस्तेमाल करके, यह बताएं कि आपका ऐप्लिकेशन किस तरह का ऑडियो चला रहा है. उदाहरण के लिए, बोली सुनाने वाले ऐप्लिकेशन के लिए,CONTENT_TYPE_SPEECH
डालें.
Android के वर्शन के हिसाब से, ऑडियो फ़ोकस को अलग-अलग तरीके से मैनेज किया जाता है:
- Android 12 (एपीआई लेवल 31) या उसके बाद का वर्शन
- ऑडियो फ़ोकस को सिस्टम मैनेज करता है. जब कोई दूसरा ऐप्लिकेशन ऑडियो फ़ोकस का अनुरोध करता है, तो सिस्टम किसी ऐप्लिकेशन से ऑडियो चलाने की सुविधा को फ़ेड आउट कर देता है. कॉल आने पर, सिस्टम ऑडियो प्लेबैक को भी म्यूट कर देता है.
- Android 8.0 (एपीआई लेवल 26) से लेकर Android 11 (एपीआई लेवल 30) तक
- ऑडियो फ़ोकस को सिस्टम मैनेज नहीं करता. हालांकि, इसमें कुछ ऐसे बदलाव शामिल हैं जिन्हें Android 8.0 (एपीआई लेवल 26) से शुरू किया गया था.
- Android 7.1 (एपीआई लेवल 25) और उससे पहले के वर्शन
- ऑडियो फ़ोकस को सिस्टम मैनेज नहीं करता. ऐप्लिकेशन,
requestAudioFocus()
औरabandonAudioFocus()
का इस्तेमाल करके ऑडियो फ़ोकस को मैनेज करते हैं.
Android 12 और उसके बाद के वर्शन में ऑडियो फ़ोकस
ऑडियो फ़ोकस का इस्तेमाल करने वाले मीडिया या गेम ऐप्लिकेशन को फ़ोकस हटने के बाद ऑडियो नहीं चलाना चाहिए. Android 12 (एपीआई लेवल 31) और उसके बाद के वर्शन में, सिस्टम इस व्यवहार को लागू करता है. जब कोई ऐप्लिकेशन ऑडियो फ़ोकस का अनुरोध करता है और फ़िलहाल किसी दूसरे ऐप्लिकेशन पर फ़ोकस है और वह ऐप्लिकेशन ऑडियो चला रहा है, तो सिस्टम उस ऐप्लिकेशन को धीरे-धीरे कम कर देता है. फ़ेड-आउट की सुविधा जोड़ने से, एक ऐप्लिकेशन से दूसरे ऐप्लिकेशन पर जाने पर आसानी से ट्रांज़िशन किया जा सकता है.
फ़ेड आउट करने की यह सुविधा तब चालू होती है, जब ये शर्तें पूरी होती हैं:
फ़िलहाल चल रहा पहला ऐप्लिकेशन, इन सभी शर्तों को पूरा करता हो:
- ऐप्लिकेशन में इस्तेमाल से जुड़ा एट्रिब्यूट,
AudioAttributes.USAGE_MEDIA
याAudioAttributes.USAGE_GAME
है. - ऐप्लिकेशन ने
AudioManager.AUDIOFOCUS_GAIN
की मदद से, ऑडियो फ़ोकस का अनुरोध किया. - ऐप्लिकेशन, कॉन्टेंट टाइप
AudioAttributes.CONTENT_TYPE_SPEECH
वाला ऑडियो नहीं चला रहा है.
- ऐप्लिकेशन में इस्तेमाल से जुड़ा एट्रिब्यूट,
दूसरा ऐप्लिकेशन,
AudioManager.AUDIOFOCUS_GAIN
के साथ ऑडियो फ़ोकस का अनुरोध करता है.
इन शर्तों के पूरा होने पर, ऑडियो सिस्टम पहले ऐप्लिकेशन को फ़ेड आउट कर देता है. फ़ेड आउट होने के बाद, सिस्टम पहले ऐप्लिकेशन को फ़ोकस हटने की सूचना देता है. ऐप्लिकेशन के प्लेयर तब तक म्यूट रहते हैं, जब तक ऐप्लिकेशन फिर से ऑडियो फ़ोकस का अनुरोध नहीं करता.
ऑडियो फ़ोकस के मौजूदा व्यवहार
आपको इन अन्य मामलों के बारे में भी पता होना चाहिए जिनमें ऑडियो फ़ोकस में बदलाव होता है.
ऑटोमैटिक डकिंग
Android 8.0 (एपीआई लेवल 26) में, ऑटोमैटिक डकिंग की सुविधा को जोड़ा गया था. इस सुविधा की मदद से, किसी ऐप्लिकेशन के ऑडियो लेवल को कुछ समय के लिए कम किया जाता है, ताकि दूसरे ऐप्लिकेशन का ऑडियो साफ़ तौर पर सुना जा सके.
सिस्टम के डकिंग की सुविधा लागू करने पर, आपको अपने ऐप्लिकेशन में डकिंग की सुविधा लागू करने की ज़रूरत नहीं होती.
ऑटो डकिंग तब भी होती है, जब कोई ऑडियो सूचना, चल रहे ऐप्लिकेशन से फ़ोकस हासिल करती है. सूचना के प्लेबैक की शुरुआत, डकिंग की प्रोसेस के खत्म होने के साथ सिंक होती है.
ऑटोमैटिक डकिंग तब होती है, जब ये शर्तें पूरी होती हैं:
फ़िलहाल चल रहा पहला ऐप्लिकेशन, इन सभी शर्तों को पूरा करता हो:
- ऐप्लिकेशन ने किसी भी तरह के फ़ोकस हासिल करने के लिए, ऑडियो फ़ोकस का अनुरोध किया.
- ऐप्लिकेशन, कॉन्टेंट टाइप
AudioAttributes.CONTENT_TYPE_SPEECH
वाला ऑडियो नहीं चला रहा है. - ऐप्लिकेशन ने
AudioFocusRequest.Builder.setWillPauseWhenDucked(true)
को सेट नहीं किया.
दूसरा ऐप्लिकेशन,
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
के साथ ऑडियो फ़ोकस का अनुरोध करता है.
इन शर्तों के पूरा होने पर, ऑडियो सिस्टम पहले ऐप्लिकेशन के सभी ऐक्टिव प्लेयर को धीमा कर देता है. ऐसा तब होता है, जब फ़ोकस दूसरे ऐप्लिकेशन पर हो. जब दूसरा ऐप्लिकेशन फ़ोकस से हट जाता है, तो वह उन्हें अनडक कर देता है. पहले ऐप्लिकेशन के फ़ोकस में न होने पर, उसे सूचना नहीं दी जाती. इसलिए, उसे कुछ भी करने की ज़रूरत नहीं होती.
ध्यान दें कि जब उपयोगकर्ता बोली वाले कॉन्टेंट को सुन रहा हो, तब ऑटोमैटिक डकिंग की सुविधा काम नहीं करती. ऐसा इसलिए, क्योंकि हो सकता है कि उपयोगकर्ता को प्रोग्राम का कुछ हिस्सा सुनाई न दे. उदाहरण के लिए, ड्राइविंग के निर्देशों के लिए बोलकर दिशा बताने की सुविधा को कम नहीं किया जाता.
आने वाले फ़ोन कॉल के लिए, चल रहे ऑडियो को म्यूट करना
कुछ ऐप्लिकेशन ठीक से काम नहीं करते और फ़ोन कॉल के दौरान ऑडियो चलाना जारी रखते हैं. इस स्थिति में, उपयोगकर्ता को कॉल सुनने के लिए, समस्या वाले ऐप्लिकेशन को ढूंढकर म्यूट करना पड़ता है या उसे बंद करना पड़ता है. इससे बचने के लिए, इनकमिंग कॉल के दौरान सिस्टम, अन्य ऐप्लिकेशन के ऑडियो को म्यूट कर सकता है. सिस्टम इस सुविधा को तब चालू करता है, जब कोई कॉल आता है और कोई ऐप्लिकेशन इन शर्तों को पूरा करता है:
- ऐप्लिकेशन में
AudioAttributes.USAGE_MEDIA
याAudioAttributes.USAGE_GAME
इस्तेमाल से जुड़ा एट्रिब्यूट मौजूद हो. - ऐप्लिकेशन ने ऑडियो फ़ोकस (किसी भी फ़ोकस गेन) का अनुरोध किया है और ऑडियो चला रहा है.
अगर कॉल के दौरान कोई ऐप्लिकेशन चलता रहता है, तो कॉल खत्म होने तक उसका प्लेबैक म्यूट कर दिया जाता है. हालांकि, अगर कॉल के दौरान कोई ऐप्लिकेशन चलना शुरू हो जाता है, तो उस प्लेयर को म्यूट नहीं किया जाता. ऐसा इसलिए किया जाता है, क्योंकि यह माना जाता है कि उपयोगकर्ता ने जान-बूझकर उसे चलाया है.
Android 8.0 से लेकर Android 11 तक के वर्शन में ऑडियो फ़ोकस
Android 8.0 (एपीआई लेवल 26) से, requestAudioFocus()
को कॉल करते समय, आपको AudioFocusRequest
पैरामीटर देना होगा. AudioFocusRequest
में, आपके ऐप्लिकेशन के ऑडियो कॉन्टेक्स्ट और सुविधाओं की जानकारी होती है. सिस्टम इस जानकारी का इस्तेमाल, ऑडियो फ़ोकस को अपने-आप कम या ज़्यादा करने के लिए करता है. ऑडियो फ़ोकस हटाने के लिए, abandonAudioFocusRequest()
वाला तरीका इस्तेमाल करें. इस तरीके में भी AudioFocusRequest
को आर्ग्युमेंट के तौर पर इस्तेमाल किया जाता है. फ़ोकस का अनुरोध करने और फ़ोकस छोड़ने के लिए, एक ही AudioFocusRequest
इंस्टेंस का इस्तेमाल करें.
AudioFocusRequest
बनाने के लिए, AudioFocusRequest.Builder
का इस्तेमाल करें. फ़ोकस अनुरोध में, अनुरोध का टाइप हमेशा बताना ज़रूरी होता है. इसलिए, बिल्डर के लिए कंस्ट्रक्टर में टाइप शामिल किया जाता है. अनुरोध के अन्य फ़ील्ड सेट करने के लिए, बिल्डर के तरीकों का इस्तेमाल करें.
FocusGain
फ़ील्ड को भरना ज़रूरी है. बाकी सभी फ़ील्ड को भरना ज़रूरी नहीं है.
Method | नोट |
---|---|
setFocusGain()
|
हर अनुरोध में यह फ़ील्ड भरना ज़रूरी है. यह वैल्यू वही होती है जो Android 8.0 से पहले के वर्शन में, requestAudioFocus() को कॉल करने के लिए इस्तेमाल की गई durationHint वैल्यू होती है:
AUDIOFOCUS_GAIN , AUDIOFOCUS_GAIN_TRANSIENT , AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK या AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE .
|
setAudioAttributes()
|
AudioAttributes से आपके ऐप्लिकेशन के इस्तेमाल के उदाहरण के बारे में पता चलता है. सिस्टम, ऐप्लिकेशन के ऑडियो फ़ोकस में आने और उससे हटने पर इनका इस्तेमाल करता है. एट्रिब्यूट, स्ट्रीम टाइप की जगह ले लेते हैं. Android 8.0 (एपीआई लेवल 26) और इसके बाद के वर्शन में, आवाज़ कंट्रोल के अलावा किसी भी ऑपरेशन के लिए स्ट्रीम टाइप का इस्तेमाल नहीं किया जा सकता. फ़ोकस अनुरोध में उन एट्रिब्यूट का इस्तेमाल करें जिनका इस्तेमाल आपने अपने ऑडियो प्लेयर में किया है. इस टेबल के बाद दिए गए उदाहरण में यह दिखाया गया है.
सबसे पहले एट्रिब्यूट तय करने के लिए
अगर कोई वैल्यू तय नहीं की गई है, तो डिफ़ॉल्ट रूप से |
setWillPauseWhenDucked()
|
जब कोई दूसरा ऐप्लिकेशन AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK का इस्तेमाल करके फ़ोकस का अनुरोध करता है, तो आम तौर पर फ़ोकस में मौजूद ऐप्लिकेशन को onAudioFocusChange() कॉलबैक नहीं मिलता. इसकी वजह यह है कि सिस्टम फ़ोकस को अपने-आप कम कर सकता है. अगर आपको आवाज़ कम करने के बजाय, वीडियो चलाना रोकना है, तो setWillPauseWhenDucked(true) को कॉल करें. इसके बाद, अपने-आप आवाज़ कम होने की सुविधा में बताए गए तरीके से OnAudioFocusChangeListener बनाएं और सेट करें.
|
setAcceptsDelayedFocusGain()
|
अगर ऑडियो फ़ोकस को किसी दूसरे ऐप्लिकेशन ने लॉक कर दिया है, तो ऑडियो फ़ोकस के लिए किया गया अनुरोध पूरा नहीं हो सकता.
इस तरीके से, फ़ोकस पाने में देरी की सुविधा चालू होती है: यह सुविधा, फ़ोकस उपलब्ध होने पर, ऐप्लिकेशन को असींक्रोनस तरीके से फ़ोकस देती है.
ध्यान दें कि फ़ोकस पाने में देरी की सुविधा सिर्फ़ तब काम करती है, जब ऑडियो अनुरोध में |
setOnAudioFocusChangeListener()
|
OnAudioFocusChangeListener की वैल्यू सिर्फ़ तब देनी होती है, जब अनुरोध में willPauseWhenDucked(true) या setAcceptsDelayedFocusGain(true) की वैल्यू भी दी गई हो.
Listener को सेट करने के दो तरीके हैं: एक, हैंडलर आर्ग्युमेंट के साथ और दूसरा, हैंडलर आर्ग्युमेंट के बिना. हैंडलर वह थ्रेड होती है जिस पर listener चलता है. अगर आपने कोई हैंडलर नहीं बताया है, तो मुख्य |
यहां दिए गए उदाहरण में, AudioFocusRequest
बनाने के लिए AudioFocusRequest.Builder
का इस्तेमाल करने और ऑडियो फ़ोकस का अनुरोध करने और उसे छोड़ने का तरीका बताया गया है:
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; } } }
ऑटोमैटिक डकिंग
Android 8.0 (एपीआई लेवल 26) में, जब कोई दूसरा ऐप्लिकेशन AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
के साथ फ़ोकस का अनुरोध करता है, तो सिस्टम ऐप्लिकेशन के onAudioFocusChange()
कॉलबैक को ट्रिगर किए बिना, वॉल्यूम को कम और फिर से बढ़ा सकता है.
संगीत और वीडियो चलाने वाले ऐप्लिकेशन के लिए, ऑडियो अपने-आप कम होने की सुविधा काम की है. हालांकि, ऑडियो बुक ऐप्लिकेशन जैसे बोले गए कॉन्टेंट को चलाने के दौरान, यह सुविधा काम की नहीं है. इस मामले में, ऐप्लिकेशन को रोकना चाहिए.
अगर आपको ऐप्लिकेशन की आवाज़ कम करने के बजाय, उसे रोकना है, तो OnAudioFocusChangeListener
के साथ onAudioFocusChange()
कॉलबैक का ऐसा तरीका बनाएं जो ऐप्लिकेशन को रोकने/फिर से चलाने की सुविधा लागू करता हो.
ऑडियंस को रजिस्टर करने के लिए, setOnAudioFocusChangeListener()
को कॉल करें. साथ ही, सिस्टम को ऑटोमैटिक डकिंग के बजाय आपके कॉलबैक का इस्तेमाल करने के लिए, setWillPauseWhenDucked(true)
को कॉल करें.
फ़ोकस में देरी
कभी-कभी सिस्टम, ऑडियो फ़ोकस के लिए अनुरोध स्वीकार नहीं कर पाता, क्योंकि फ़ोकस को किसी दूसरे ऐप्लिकेशन ने "लॉक" कर रखा है. जैसे, फ़ोन कॉल के दौरान. इस मामले में,
requestAudioFocus()
से AUDIOFOCUS_REQUEST_FAILED
मिलता है. ऐसा होने पर, आपके ऐप्लिकेशन को ऑडियो चलाना बंद कर देना चाहिए, क्योंकि उस पर फ़ोकस नहीं है.
setAcceptsDelayedFocusGain(true)
, एक ऐसा तरीका है जिसकी मदद से आपका ऐप्लिकेशन, फ़ोकस के अनुरोध को अलग-अलग समय पर मैनेज कर सकता है. इस फ़्लैग के सेट होने पर, फ़ोकस लॉक होने पर किया गया अनुरोध AUDIOFOCUS_REQUEST_DELAYED
दिखाता है. जब ऑडियो फ़ोकस को लॉक करने वाली शर्त मौजूद न हो, जैसे कि फ़ोन कॉल खत्म होने पर, सिस्टम फ़ोकस के लिए किए गए अनुरोध को स्वीकार कर लेता है. साथ ही, आपके ऐप्लिकेशन को सूचना देने के लिए onAudioFocusChange()
को कॉल करता है.
फ़ोकस में आने में लगने वाले समय को मैनेज करने के लिए, आपको onAudioFocusChange()
कॉलबैक वाले तरीके के साथ एक OnAudioFocusChangeListener
बनाना होगा. यह तरीका, आपकी पसंद के हिसाब से काम करता है. साथ ही, setOnAudioFocusChangeListener()
को कॉल करके, लिसनर को रजिस्टर करता है.
Android 7.1 और इससे पहले के वर्शन में ऑडियो फ़ोकस
requestAudioFocus()
को कॉल करते समय, आपको अवधि का संकेत देना होगा. यह संकेत, फ़िलहाल फ़ोकस में मौजूद और चल रहे किसी दूसरे ऐप्लिकेशन को दिया जा सकता है:
- अगर आपको आने वाले समय में ऑडियो चलाना है, तो ऑडियो फ़ोकस (
AUDIOFOCUS_GAIN
) का हमेशा के लिए अनुरोध करें. उदाहरण के लिए, संगीत चलाते समय. साथ ही, आपको यह भी उम्मीद है कि ऑडियो फ़ोकस का पिछला होल्डर ऑडियो चलाना बंद कर दे. - जब आपको ऑडियो को सिर्फ़ कुछ समय के लिए चलाना हो और आप चाहें कि ऑडियो चलाने का अधिकार रखने वाला व्यक्ति उसे रोक दे, तो ट्रांज़िएंट फ़ोकस (
AUDIOFOCUS_GAIN_TRANSIENT
) का अनुरोध करें. - डकिंग (
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
) के साथ ट्रांज़िएंट फ़ोकस का अनुरोध करें, ताकि यह पता चल सके कि आपको ऑडियो को सिर्फ़ कुछ समय के लिए चलाना है. साथ ही, यह भी पता चल सके कि फ़ोकस के पिछले मालिक के लिए, ऑडियो आउटपुट को "डक" (कम) करके चलाना ठीक है. दोनों ऑडियो आउटपुट को ऑडियो स्ट्रीम में मिक्स किया जाता है. डकिंग की सुविधा, उन ऐप्लिकेशन के लिए खास तौर पर सही है जो ऑडियो स्ट्रीम का इस्तेमाल कभी-कभी करते हैं. जैसे, गाड़ी चलाते समय निर्देश सुनने के लिए.
requestAudioFocus()
तरीके के लिए भी AudioManager.OnAudioFocusChangeListener
की ज़रूरत होती है. इस लिसनर को उसी गतिविधि या सेवा में बनाया जाना चाहिए जिसके पास आपके मीडिया सेशन का मालिकाना हक है. यह उस कॉलबैक onAudioFocusChange()
को लागू करता है जो आपके ऐप्लिकेशन को तब मिलता है, जब कोई दूसरा ऐप्लिकेशन ऑडियो फ़ोकस हासिल करता है या छोड़ता है.
यहां दिया गया स्निपेट, स्ट्रीम STREAM_MUSIC
पर ऑडियो फ़ोकस को हमेशा के लिए सेट करने का अनुरोध करता है. साथ ही, ऑडियो फ़ोकस में होने वाले बाद के बदलावों को मैनेज करने के लिए, OnAudioFocusChangeListener
को रजिस्टर करता है. (बदलाव सुनने वाले के बारे में ऑडियो फ़ोकस में बदलाव होने पर जवाब देना में बताया गया है.)
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 }
वीडियो चलाने के बाद, abandonAudioFocus()
को कॉल करें.
Kotlin
audioManager.abandonAudioFocus(afChangeListener)
Java
// Abandon audio focus when playback complete audioManager.abandonAudioFocus(afChangeListener);
इससे सिस्टम को यह सूचना मिलती है कि आपको अब फ़ोकस की ज़रूरत नहीं है. साथ ही, इससे उससे जुड़े OnAudioFocusChangeListener
को अनरजिस्टर कर दिया जाता है. अगर आपने कुछ समय के लिए फ़ोकस करने का अनुरोध किया है, तो इससे उस ऐप्लिकेशन को सूचना मिलेगी जिसे रोका गया है या जिसकी आवाज़ कम की गई है. इससे, ऐप्लिकेशन को फिर से चलाया जा सकता है या उसकी आवाज़ को पहले जैसा किया जा सकता है.
ऑडियो फ़ोकस में बदलाव होने पर जवाब देना
जब कोई ऐप्लिकेशन ऑडियो फ़ोकस हासिल करता है, तो उसे ऑडियो फ़ोकस छोड़ना होगा, जब कोई दूसरा ऐप्लिकेशन ऑडियो फ़ोकस के लिए अनुरोध करता है. ऐसा होने पर, आपके ऐप्लिकेशन को AudioFocusChangeListener
में मौजूद onAudioFocusChange()
तरीके का कॉल मिलता है. यह तरीका, requestAudioFocus()
को कॉल करते समय तय किया गया था.
onAudioFocusChange()
में पास किया गया focusChange
पैरामीटर, होने वाले बदलाव के टाइप के बारे में बताता है. यह उस ऐप्लिकेशन के इस्तेमाल की अवधि के संकेत से मेल खाता है जिस पर फ़ोकस किया जा रहा है. आपका ऐप्लिकेशन, सही तरीके से जवाब देना चाहिए.
- फ़ोकस में कुछ समय के लिए कमी आना
-
अगर फ़ोकस में बदलाव कुछ समय के लिए होता है (
AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK
याAUDIOFOCUS_LOSS_TRANSIENT
), तो आपका ऐप्लिकेशन डक (अगर अपने-आप डक होने की सुविधा का इस्तेमाल नहीं किया जा रहा है) या वीडियो चलाना रोक देना चाहिए. हालांकि, बाकी चीज़ें पहले जैसी ही रहनी चाहिए.ऑडियो फ़ोकस के कुछ समय के लिए बंद होने पर, आपको ऑडियो फ़ोकस में होने वाले बदलावों पर नज़र बनाए रखनी चाहिए. साथ ही, फ़ोकस वापस मिलने पर, सामान्य प्लेबैक को फिर से शुरू करने के लिए तैयार रहना चाहिए. जब ब्लॉक करने वाला ऐप्लिकेशन फ़ोकस छोड़ देता है, तो आपको कॉलबैक (
AUDIOFOCUS_GAIN
) मिलता है. इस समय, वॉल्यूम को सामान्य लेवल पर वापस लाया जा सकता है या वीडियो चलाना फिर से शुरू किया जा सकता है. - फ़ोकस हमेशा के लिए खत्म हो जाना
-
अगर ऑडियो पर फ़ोकस हमेशा के लिए हट जाता है (
AUDIOFOCUS_LOSS
), तो इसका मतलब है कि कोई दूसरा ऐप्लिकेशन ऑडियो चला रहा है. आपके ऐप्लिकेशन को तुरंत प्लेबैक रोक देना चाहिए, क्योंकि उसे कभी भीAUDIOFOCUS_GAIN
कॉलबैक नहीं मिलेगा. वीडियो चलाना फिर से शुरू करने के लिए, उपयोगकर्ता को साफ़ तौर पर कोई कार्रवाई करनी होगी. जैसे, सूचना या ऐप्लिकेशन के यूज़र इंटरफ़ेस (यूआई) में, वीडियो चलाने के लिए बने कंट्रोल को दबाना.
नीचे दिए गए कोड स्निपेट में, OnAudioFocusChangeListener
और उसके onAudioFocusChange()
कॉलबैक को लागू करने का तरीका बताया गया है. ऑडियो फ़ोकस हमेशा के लिए हटने पर, Handler
का इस्तेमाल करके, रोकें कॉलबैक को देर से भेजने का तरीका जानें.
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 } } };
हैंडलर, Runnable
का इस्तेमाल करता है, जो कुछ ऐसा दिखता है:
Kotlin
private var delayedStopRunnable = Runnable { mediaController.transportControls.stop() }
Java
private Runnable delayedStopRunnable = new Runnable() { @Override public void run() { getMediaController().getTransportControls().stop(); } };
यह पक्का करने के लिए कि उपयोगकर्ता के वीडियो को फिर से चलाने पर, वीडियो अपने-आप बंद न हो, किसी भी स्थिति में बदलाव होने पर mHandler.removeCallbacks(mDelayedStopRunnable)
को कॉल करें. उदाहरण के लिए, अपने कॉलबैक के onPlay()
,
onSkipToNext()
वगैरह में removeCallbacks()
को कॉल करें. साथ ही, अपनी सेवा के इस्तेमाल किए गए संसाधनों को हटाते समय, आपको अपनी सेवा के
onDestroy()
कॉलबैक में भी इस तरीके को कॉल करना चाहिए.