ऑडियो फ़ोकस को मैनेज करें

दो या उससे ज़्यादा 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) और इसके बाद के वर्शन में, सिस्टम इस व्यवहार को लागू करता है. जब कोई ऐप्लिकेशन ऑडियो फ़ोकस का अनुरोध करता है, जबकि किसी दूसरे ऐप्लिकेशन के पास फ़ोकस होता है और वह ऑडियो चला रहा होता है, तो सिस्टम ऑडियो चलाने वाले ऐप्लिकेशन को फ़ेड आउट कर देता है. फ़ेड-आउट इफ़ेक्ट जोड़ने से, एक ऐप्लिकेशन से दूसरे ऐप्लिकेशन पर जाने के दौरान ट्रांज़िशन ज़्यादा बेहतर होता है.

यह फ़ेड आउट तब होता है, जब ये शर्तें पूरी होती हैं:

  1. फ़िलहाल, चल रहे ऐप्लिकेशन के लिए ये सभी शर्तें पूरी होनी चाहिए:

  2. दूसरा ऐप्लिकेशन, AudioManager.AUDIOFOCUS_GAIN का इस्तेमाल करके ऑडियो फ़ोकस का अनुरोध करता है.

इन शर्तों के पूरा होने पर, ऑडियो सिस्टम पहले ऐप्लिकेशन का ऑडियो कम कर देता है. ऑडियो कम होने के बाद, सिस्टम पहले ऐप्लिकेशन को फ़ोकस खोने की सूचना देता है. ऐप्लिकेशन के प्लेयर तब तक म्यूट रहते हैं, जब तक ऐप्लिकेशन फिर से ऑडियो फ़ोकस का अनुरोध नहीं करता.

ऑडियो फ़ोकस करने के मौजूदा तरीके

आपको इन अन्य मामलों के बारे में भी पता होना चाहिए, जिनमें ऑडियो फ़ोकस बदलता है.

ऑटोमैटिक डकिंग

ऑटोमैटिक डकिंग (एक ऐप्लिकेशन के ऑडियो लेवल को कुछ समय के लिए कम करना, ताकि दूसरे ऐप्लिकेशन का ऑडियो साफ़ तौर पर सुना जा सके) की सुविधा, Android 8.0 (एपीआई लेवल 26) में जोड़ी गई थी.

सिस्टम को डकिंग लागू करने की अनुमति देने पर, आपको अपने ऐप्लिकेशन में डकिंग लागू करने की ज़रूरत नहीं होती.

जब कोई ऑडियो सूचना, किसी ऐप्लिकेशन से फ़ोकस हटाती है, तब भी आवाज़ अपने-आप कम हो जाती है. सूचना के चलने की शुरुआत, आवाज़ कम होने की प्रोसेस के खत्म होने के साथ सिंक होती है.

ऑडियो डकिंग की सुविधा अपने-आप तब चालू होती है, जब ये शर्तें पूरी होती हैं:

  1. फ़िलहाल, चल रहे ऐप्लिकेशन के लिए ये सभी शर्तें पूरी होनी चाहिए:

    • ऐप्लिकेशन ने किसी भी तरह के focus gain के साथ ऑडियो फ़ोकस का अनुरोध किया है.
    • ऐप्लिकेशन, AudioAttributes.CONTENT_TYPE_SPEECH कॉन्टेंट टाइप के साथ ऑडियो नहीं चला रहा है.
    • ऐप्लिकेशन ने AudioFocusRequest.Builder.setWillPauseWhenDucked(true) सेट नहीं किया.
  2. दूसरा ऐप्लिकेशन, 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) और इसके बाद के वर्शन में, वॉल्यूम कंट्रोल के अलावा किसी भी अन्य ऑपरेशन के लिए स्ट्रीम टाइप बंद कर दिए गए हैं. फ़ोकस के अनुरोध में, उन्हीं एट्रिब्यूट का इस्तेमाल करें जिनका इस्तेमाल ऑडियो प्लेयर में किया जाता है. इस टेबल के बाद दिए गए उदाहरण में, इसे दिखाया गया है.

सबसे पहले एट्रिब्यूट तय करने के लिए, AudioAttributes.Builder का इस्तेमाल करें. इसके बाद, अनुरोध में एट्रिब्यूट असाइन करने के लिए इस तरीके का इस्तेमाल करें.

अगर AudioAttributes की वैल्यू नहीं दी गई है, तो डिफ़ॉल्ट रूप से AudioAttributes.USAGE_MEDIA को चुना जाता है.

setWillPauseWhenDucked() जब कोई दूसरा ऐप्लिकेशन AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK के साथ फ़ोकस करने का अनुरोध करता है, तो फ़ोकस करने वाले ऐप्लिकेशन को आम तौर पर onAudioFocusChange() कॉलबैक नहीं मिलता है. ऐसा इसलिए होता है, क्योंकि सिस्टम अपने-आप डकिंग कर सकता है. अगर आपको आवाज़ कम करने के बजाय, ऑडियो को रोकना है, तो setWillPauseWhenDucked(true) को कॉल करें. इसके बाद, setWillPauseWhenDucked(true) बनाएं और सेट करें. इसके बारे में ऑटोमैटिक डकिंग में बताया गया है.OnAudioFocusChangeListener
setAcceptsDelayedFocusGain() ऑडियो फ़ोकस के लिए किया गया अनुरोध तब पूरा नहीं हो पाता, जब फ़ोकस को किसी दूसरे ऐप्लिकेशन ने लॉक किया हो. इस तरीके से फ़ोकस पाने में देरी की सुविधा चालू होती है: जब फ़ोकस उपलब्ध हो जाता है, तब एसिंक्रोनस तरीके से फ़ोकस पाने की सुविधा.

ध्यान दें कि फ़ोकस पाने में देरी होने की सुविधा सिर्फ़ तब काम करती है, जब आपने ऑडियो के अनुरोध में AudioManager.OnAudioFocusChangeListener भी तय किया हो. ऐसा इसलिए, क्योंकि आपके ऐप्लिकेशन को यह जानने के लिए कि फ़ोकस दिया गया है, कॉलबैक मिलना ज़रूरी है.

setOnAudioFocusChangeListener() OnAudioFocusChangeListener की ज़रूरत सिर्फ़ तब होती है, जब अनुरोध में willPauseWhenDucked(true) या setAcceptsDelayedFocusGain(true) भी शामिल किया गया हो.

लिसनर सेट करने के दो तरीके हैं: एक में हैंडलर आर्ग्युमेंट होता है और दूसरे में नहीं होता. हैंडलर वह थ्रेड होता है जिस पर लिसनर चलता है. अगर आपने हैंडलर के बारे में नहीं बताया है, तो मुख्य Looper से जुड़े हैंडलर का इस्तेमाल किया जाता है.

यहां दिए गए उदाहरण में, AudioFocusRequest.Builder का इस्तेमाल करके AudioFocusRequest बनाने और ऑडियो फ़ोकस का अनुरोध करने और उसे छोड़ने का तरीका बताया गया है:

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() कॉलबैक तरीके के साथ एक � बनाना होगा. यह तरीका, फ़ोकस में आने के लिए ज़रूरी व्यवहार को लागू करता है. साथ ही, setOnAudioFocusChangeListener() को कॉल करके लिसनर को रजिस्टर करता है.OnAudioFocusChangeListener

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() कॉलबैक में भी कॉल करना चाहिए, ताकि आपकी सेवा के इस्तेमाल किए गए संसाधनों को हटाया जा सके.