ब्रॉडकास्ट की खास जानकारी

Android ऐप्लिकेशन, Android सिस्टम और अन्य Android ऐप्लिकेशन से ब्रॉडकास्ट मैसेज भेजते और पाते हैं. यह पब्लिश-सब्सक्राइब डिज़ाइन पैटर्न की तरह होता है. आम तौर पर, सिस्टम और ऐप्लिकेशन कुछ इवेंट होने पर ब्रॉडकास्ट भेजते हैं. उदाहरण के लिए, Android सिस्टम, सिस्टम से जुड़े अलग-अलग इवेंट होने पर ब्रॉडकास्ट भेजता है. जैसे, सिस्टम बूट होने या डिवाइस चार्ज होने पर. ऐप्लिकेशन, कस्टम ब्रॉडकास्ट भी भेजते हैं. उदाहरण के लिए, वे अन्य ऐप्लिकेशन को ऐसी किसी चीज़ के बारे में सूचना देते हैं जिसमें उनकी दिलचस्पी हो सकती है. जैसे, नया डेटा डाउनलोड करना.

ऐप्लिकेशन, किसी खास ब्रॉडकास्ट को पाने के लिए रजिस्टर कर सकते हैं. ब्रॉडकास्ट भेजे जाने पर, सिस्टम उन्हें उन ऐप्लिकेशन पर अपने-आप भेज देता है जिन्होंने उस तरह के ब्रॉडकास्ट पाने के लिए सदस्यता ली है.

आम तौर पर, ब्रॉडकास्ट का इस्तेमाल ऐप्लिकेशन और उपयोगकर्ता के सामान्य फ़्लो के बाहर, मैसेजिंग सिस्टम के तौर पर किया जा सकता है. हालांकि, आपको ब्रॉडकास्ट का जवाब देने और बैकग्राउंड में ऐसे टास्क चलाने के मौके का गलत इस्तेमाल नहीं करना चाहिए जिनकी वजह से सिस्टम की परफ़ॉर्मेंस धीमी हो सकती है.

सिस्टम ब्रॉडकास्ट के बारे में जानकारी

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

Intent ऑब्जेक्ट, ब्रॉडकास्ट मैसेज को रैप करता है. action स्ट्रिंग से, उस इवेंट की पहचान होती है जो हुआ है. जैसे, android.intent.action.AIRPLANE_MODE. इंटेंट में, अतिरिक्त फ़ील्ड में बंडल की गई ज़्यादा जानकारी भी शामिल हो सकती है. उदाहरण के लिए, फ़्लाइट मोड के इंटेंट में एक बूलियन एक्स्ट्रा शामिल होता है. इससे पता चलता है कि फ़्लाइट मोड चालू है या नहीं.

किसी इंटेंट से इंटेंट पढ़ने और कार्रवाई की स्ट्रिंग पाने के तरीके के बारे में ज़्यादा जानने के लिए, इंटेंट और इंटेंट फ़िल्टर देखें.

सिस्टम ब्रॉडकास्ट से जुड़ी कार्रवाइयां

सिस्टम ब्रॉडकास्ट ऐक्शन की पूरी सूची देखने के लिए, Android SDK में मौजूद BROADCAST_ACTIONS.TXT फ़ाइल देखें. हर ब्रॉडकास्ट ऐक्शन से एक कॉन्स्टेंट फ़ील्ड जुड़ा होता है. उदाहरण के लिए, कॉन्स्टेंट ACTION_AIRPLANE_MODE_CHANGED की वैल्यू android.intent.action.AIRPLANE_MODE है. हर ब्रॉडकास्ट ऐक्शन के लिए दस्तावेज़, उससे जुड़े कॉन्स्टेंट फ़ील्ड में उपलब्ध होता है.

सिस्टम ब्रॉडकास्ट में बदलाव

Android प्लैटफ़ॉर्म में बदलाव होने पर, सिस्टम ब्रॉडकास्ट के काम करने के तरीके में समय-समय पर बदलाव होता है. Android के सभी वर्शन के साथ काम करने के लिए, इन बदलावों को ध्यान में रखें.

Android 16

Android 16 में, अलग-अलग प्रोसेस में android:priority एट्रिब्यूट या IntentFilter.setPriority() का इस्तेमाल करके ब्रॉडकास्ट डिलीवरी के क्रम की गारंटी नहीं दी जाएगी. ब्रॉडकास्ट की प्राथमिकताएं, सभी प्रोसेस के बजाय सिर्फ़ एक ही ऐप्लिकेशन प्रोसेस में लागू होती हैं.

साथ ही, ब्रॉडकास्ट की प्राथमिकताएं अपने-आप इस रेंज तक सीमित हो जाती हैं: (SYSTEM_LOW_PRIORITY + 1, SYSTEM_HIGH_PRIORITY - 1). सिर्फ़ सिस्टम कॉम्पोनेंट को ब्रॉडकास्ट की प्राथमिकता के तौर पर SYSTEM_LOW_PRIORITY, SYSTEM_HIGH_PRIORITY सेट करने की अनुमति है.

Android 14

जब ऐप्लिकेशन कैश किए गए डेटा की स्थिति में होते हैं, तब सिस्टम की परफ़ॉर्मेंस को बेहतर बनाने के लिए, सिस्टम ब्रॉडकास्ट डिलीवरी को ऑप्टिमाइज़ करता है. उदाहरण के लिए, जब ऐप्लिकेशन कैश मेमोरी में सेव होता है, तब सिस्टम कम ज़रूरी सिस्टम ब्रॉडकास्ट को कुछ समय के लिए रोक देता है. जैसे, ACTION_SCREEN_ON. जब ऐप्लिकेशन, कैश मेमोरी में सेव होने की स्थिति से ऐक्टिव प्रोसेस लाइफ़साइकल में चला जाता है, तब सिस्टम, टाले गए ब्रॉडकास्ट डिलीवर करता है.

मेनिफ़ेस्ट में बताई गई ज़रूरी ब्रॉडकास्ट के लिए, ऐप्लिकेशन को कुछ समय के लिए कैश मेमोरी से हटा दिया जाता है, ताकि उन्हें डिलीवर किया जा सके.

Android 9

Android 9 (एपीआई लेवल 28) से, NETWORK_STATE_CHANGED_ACTION ब्रॉडकास्ट को उपयोगकर्ता की जगह की जानकारी या व्यक्तिगत पहचान से जुड़ा डेटा नहीं मिलता है.

अगर आपका ऐप्लिकेशन, Android 9.0 (एपीआई लेवल 28) या उसके बाद के वर्शन वाले डिवाइस पर इंस्टॉल है, तो सिस्टम वाई-फ़ाई ब्रॉडकास्ट में एसएसआईडी, बीएसएसआईडी, कनेक्शन की जानकारी या स्कैन के नतीजे शामिल नहीं करता है. यह जानकारी पाने के लिए, getConnectionInfo() को कॉल करें.

Android 8.0

Android 8.0 (एपीआई लेवल 26) से, सिस्टम, मेनिफ़ेस्ट में बताए गए रिसीवर पर अतिरिक्त पाबंदियां लगाता है.

अगर आपका ऐप्लिकेशन Android 8.0 या इसके बाद के वर्शन को टारगेट करता है, तो मेनिफ़ेस्ट का इस्तेमाल करके, ज़्यादातर इंप्लिसिट ब्रॉडकास्ट (ऐसे ब्रॉडकास्ट जो खास तौर पर आपके ऐप्लिकेशन को टारगेट नहीं करते) के लिए रिसीवर का एलान नहीं किया जा सकता. जब उपयोगकर्ता आपके ऐप्लिकेशन का इस्तेमाल कर रहा हो, तब भी कॉन्टेक्स्ट-रजिस्टर्ड रिसीवर का इस्तेमाल किया जा सकता है.

Android 7.0

Android 7.0 (एपीआई लेवल 24) और इसके बाद के वर्शन पर, सिस्टम ब्रॉडकास्ट नहीं भेजे जाते:

इसके अलावा, Android 7.0 और इसके बाद के वर्शन को टारगेट करने वाले ऐप्लिकेशन को, CONNECTIVITY_ACTION ब्रॉडकास्ट को रजिस्टर करना होगा. इसके लिए, registerReceiver(BroadcastReceiver, IntentFilter) का इस्तेमाल करना होगा. मेनिफ़ेस्ट में रिसीवर को शामिल करने से काम नहीं चलता.

ब्रॉडकास्ट पाना

ऐप्लिकेशन को दो तरीकों से ब्रॉडकास्ट मिल सकते हैं: कॉन्टेक्स्ट-रजिस्टर्ड रिसीवर और मेनिफ़ेस्ट-डिक्लेयर्ड रिसीवर के ज़रिए.

कॉन्टेक्स्ट-रजिस्टर्ड रिसीवर

कॉन्टेक्स्ट के हिसाब से रजिस्टर किए गए रिसीवर को ब्रॉडकास्ट तब तक मिलते हैं, जब तक उनका रजिस्टर किया गया कॉन्टेक्स्ट मान्य होता है. आम तौर पर, यह registerReceiver और unregisterReceiver के बीच होता है. जब सिस्टम, रजिस्टर किए गए कॉन्टेक्स्ट को मिटा देता है, तब रजिस्टर किया गया कॉन्टेक्स्ट भी अमान्य हो जाता है. उदाहरण के लिए, अगर आपने Activity कॉन्टेक्स्ट में रजिस्टर किया है, तो आपको ब्रॉडकास्ट तब तक मिलते रहेंगे, जब तक गतिविधि चालू रहेगी. ऐप्लिकेशन कॉन्टेक्स्ट के साथ रजिस्टर करने पर, ऐप्लिकेशन के चालू रहने तक आपको ब्रॉडकास्ट मिलते हैं.

किसी कॉन्टेक्स्ट के साथ रिसीवर को रजिस्टर करने के लिए, यह तरीका अपनाएं:

  1. अपने ऐप्लिकेशन के मॉड्यूल-लेवल की बिल्ड फ़ाइल में, AndroidX Core लाइब्रेरी का 1.9.0 या इसके बाद का वर्शन शामिल करें:

    Groovy

    dependencies {
        def core_version = "1.19.1"
    
        // Java language implementation
        implementation "androidx.core:core:$core_version"
        // Kotlin
        implementation "androidx.core:core-ktx:$core_version"
    
        // To use RoleManagerCompat
        implementation "androidx.core:core-role:1.1.0"
    
        // To use the Animator APIs
        implementation "androidx.core:core-animation:1.0.0"
        // To test the Animator APIs
        androidTestImplementation "androidx.core:core-animation-testing:1.0.0"
    
        // Optional - To enable APIs that query the performance characteristics of GMS devices.
        implementation "androidx.core:core-performance:1.0.0"
    
        // Optional - to use ShortcutManagerCompat to donate shortcuts to be used by Google
        implementation "androidx.core:core-google-shortcuts:1.1.0"
    
        // Optional - to support backwards compatibility of RemoteViews
        implementation "androidx.core:core-remoteviews:1.1.0"
    
        // Optional - APIs for SplashScreen, including compatibility helpers on devices prior Android 12
        implementation "androidx.core:core-splashscreen:1.2.0"
    }

    Kotlin

    dependencies {
        val core_version = "1.19.1"
    
        // Java language implementation
        implementation("androidx.core:core:$core_version")
        // Kotlin
        implementation("androidx.core:core-ktx:$core_version")
    
        // To use RoleManagerCompat
        implementation("androidx.core:core-role:1.1.0")
    
        // To use the Animator APIs
        implementation("androidx.core:core-animation:1.0.0")
        // To test the Animator APIs
        androidTestImplementation("androidx.core:core-animation-testing:1.0.0")
    
        // Optional - To enable APIs that query the performance characteristics of GMS devices.
        implementation("androidx.core:core-performance:1.0.0")
    
        // Optional - to use ShortcutManagerCompat to donate shortcuts to be used by Google
        implementation("androidx.core:core-google-shortcuts:1.1.0")
    
        // Optional - to support backwards compatibility of RemoteViews
        implementation("androidx.core:core-remoteviews:1.1.0")
    
        // Optional - APIs for SplashScreen, including compatibility helpers on devices prior Android 12
        implementation("androidx.core:core-splashscreen:1.2.0")
    }
  2. BroadcastReceiver का इंस्टेंस बनाएं:

    Kotlin

    val myBroadcastReceiver = MyBroadcastReceiver()
    

    Java

    MyBroadcastReceiver myBroadcastReceiver = new MyBroadcastReceiver();
    
  3. IntentFilter का इंस्टेंस बनाएं:

    Kotlin

    val filter = IntentFilter("com.example.snippets.ACTION_UPDATE_DATA")
    

    Java

    IntentFilter filter = new IntentFilter("com.example.snippets.ACTION_UPDATE_DATA");
    
  4. चुनें कि ब्रॉडकास्ट रिसीवर को एक्सपोर्ट किया जाना चाहिए या नहीं. साथ ही, यह भी चुनें कि वह डिवाइस पर मौजूद अन्य ऐप्लिकेशन को दिखना चाहिए या नहीं. अगर यह रिसीवर, सिस्टम या अन्य ऐप्लिकेशन से भेजे गए ब्रॉडकास्ट सुन रहा है, तो RECEIVER_EXPORTED फ़्लैग का इस्तेमाल करें. भले ही, वे ऐप्लिकेशन आपके हों. अगर यह रिसीवर सिर्फ़ आपके ऐप्लिकेशन से भेजे गए ब्रॉडकास्ट सुन रहा है, तो RECEIVER_NOT_EXPORTED फ़्लैग का इस्तेमाल करें.

    Kotlin

    val listenToBroadcastsFromOtherApps = false
    val receiverFlags = if (listenToBroadcastsFromOtherApps) {
        ContextCompat.RECEIVER_EXPORTED
    } else {
        ContextCompat.RECEIVER_NOT_EXPORTED
    }
    

    Java

    boolean listenToBroadcastsFromOtherApps = false;
    int receiverFlags = listenToBroadcastsFromOtherApps
            ? ContextCompat.RECEIVER_EXPORTED
            : ContextCompat.RECEIVER_NOT_EXPORTED;
    
  5. registerReceiver() को कॉल करके, रिसीवर को रजिस्टर करें:

    Kotlin

    ContextCompat.registerReceiver(context, myBroadcastReceiver, filter, receiverFlags)
    

    Java

    ContextCompat.registerReceiver(context, myBroadcastReceiver, filter, receiverFlags);
    
  6. ब्रॉडकास्ट पाना बंद करने के लिए, unregisterReceiver(android.content.BroadcastReceiver) पर कॉल करें. जब आपको रिसीवर की ज़रूरत न हो या कॉन्टेक्स्ट अब मान्य न हो, तो उसे अनरजिस्टर करना न भूलें.

ब्रॉडकास्ट रिसीवर को रजिस्टर करने की सुविधा बंद करना

ब्रॉडकास्ट रिसीवर रजिस्टर होने के दौरान, यह उस कॉन्टेक्स्ट का रेफ़रंस सेव करता है जिसके साथ आपने इसे रजिस्टर किया था. अगर ईमेल पाने वाले व्यक्ति का रजिस्टर किया गया स्कोप, कॉन्टेक्स्ट लाइफ़साइकल स्कोप से ज़्यादा है, तो इससे जानकारी लीक हो सकती है. उदाहरण के लिए, ऐसा तब हो सकता है, जब आपने किसी गतिविधि के स्कोप पर रिसीवर को रजिस्टर किया हो, लेकिन सिस्टम के गतिविधि को बंद करने पर, आपने उसे अनरजिस्टर न किया हो. इसलिए, ब्रॉडकास्ट रिसीवर को हमेशा अनरजिस्टर करें.

Kotlin

class MyActivity : ComponentActivity() {
    private val myBroadcastReceiver = MyBroadcastReceiver()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // ...
        ContextCompat.registerReceiver(this, myBroadcastReceiver, filter, receiverFlags)
        setContent { MyApp() }
    }

    override fun onDestroy() {
        super.onDestroy()
        // When you forget to unregister your receiver here, you're causing a leak!
        this.unregisterReceiver(myBroadcastReceiver)
    }
}

Java

class MyActivity extends ComponentActivity {
    MyBroadcastReceiver myBroadcastReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // ...
        ContextCompat.registerReceiver(this, myBroadcastReceiver, filter, receiverFlags);
        // Set content
    }
}

सबसे छोटे स्कोप में रिसीवर रजिस्टर करें

ब्रॉडकास्ट रिसीवर को सिर्फ़ तब रजिस्टर किया जाना चाहिए, जब आपको वाकई में नतीजे में दिलचस्पी हो. सबसे छोटा रिसीवर स्कोप चुनें:

  • LifecycleResumeEffect या गतिविधि onResume/onPause के लाइफ़साइकल के तरीके: ब्रॉडकास्ट रिसीवर को सिर्फ़ तब अपडेट मिलते हैं, जब ऐप्लिकेशन फिर से शुरू किया गया हो.
  • LifecycleStartEffect या गतिविधि onStart/onStop लाइफ़साइकल के तरीके: ब्रॉडकास्ट रिसीवर को सिर्फ़ तब अपडेट मिलते हैं, जब ऐप्लिकेशन फिर से शुरू किया गया हो.
  • DisposableEffect: ब्रॉडकास्ट रिसीवर को सिर्फ़ तब अपडेट मिलते हैं, जब कंपोज़ेबल कंपोज़िशन ट्री में होता है. यह स्कोप, गतिविधि के लाइफ़साइकल स्कोप से अटैच नहीं है. ऐप्लिकेशन के कॉन्टेक्स्ट में, ईमेल पाने वाले व्यक्ति को रजिस्टर करें. ऐसा इसलिए होता है, क्योंकि कंपोज़ेबल, गतिविधि के लाइफ़साइकल स्कोप से ज़्यादा समय तक चल सकता है और गतिविधि को लीक कर सकता है.
  • गतिविधि onCreate/onDestroy: गतिविधि के बनाए जाने के दौरान, ब्रॉडकास्ट रिसीवर को अपडेट मिलते हैं. पक्का करें कि आपने onDestroy() में अनरजिस्टर किया हो, न कि onSaveInstanceState(Bundle) में. ऐसा इसलिए, क्योंकि हो सकता है कि इसे कॉल न किया जाए.
  • कस्टम स्कोप: उदाहरण के लिए, अपने ViewModel स्कोप में किसी रिसीवर को रजिस्टर किया जा सकता है, ताकि वह गतिविधि को फिर से बनाने के बाद भी बना रहे. पक्का करें कि रिसीवर को रजिस्टर करने के लिए, ऐप्लिकेशन कॉन्टेक्स्ट का इस्तेमाल किया गया हो. ऐसा इसलिए, क्योंकि रिसीवर, गतिविधि के लाइफ़साइकल स्कोप से ज़्यादा समय तक चल सकता है और गतिविधि को लीक कर सकता है.

स्टेटफ़ुल और स्टेटलेस कंपोज़ेबल बनाना

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

Compose में सबसे सही तरीके के तौर पर, हमारा सुझाव है कि आप अपने कंपोज़ेबल को स्टेटफ़ुल और स्टेटलेस वर्शन में बांटें. इसलिए, हमारा सुझाव है कि आप ब्रॉडकास्ट रिसीवर को कंपोज़ेबल से बाहर ले जाएं, ताकि यह स्टेटलेस हो जाए:

@Composable
fun MyStatefulScreen() {
    val myBroadcastReceiver = remember { MyBroadcastReceiver() }
    val context = LocalContext.current
    LifecycleStartEffect(true) {
        // ...
        ContextCompat.registerReceiver(context, myBroadcastReceiver, filter, flags)
        onStopOrDispose { context.unregisterReceiver(myBroadcastReceiver) }
    }
    MyStatelessScreen()
}

@Composable
fun MyStatelessScreen() {
    // Implement your screen
}

मेनिफ़ेस्ट में बताए गए रिसीवर

अगर आपने अपने मेनिफ़ेस्ट में ब्रॉडकास्ट रिसीवर का एलान किया है, तो ब्रॉडकास्ट भेजे जाने पर सिस्टम आपके ऐप्लिकेशन को लॉन्च करता है. अगर ऐप्लिकेशन पहले से नहीं चल रहा है, तो सिस्टम उसे लॉन्च करता है.

ब्रॉडकास्ट रिसीवर को मेनिफ़ेस्ट में शामिल करने के लिए, यह तरीका अपनाएं:

  1. अपने ऐप्लिकेशन के मेनिफ़ेस्ट में <receiver> एलिमेंट के बारे में बताएं.

    <!-- If this receiver listens for broadcasts sent from the system or from
         other apps, even other apps that you own, set android:exported to "true". -->
    <receiver android:name=".MyBroadcastReceiver" android:exported="false">
        <intent-filter>
            <action android:name="com.example.snippets.ACTION_UPDATE_DATA" />
        </intent-filter>
    </receiver>
    

    इंटेंट फ़िल्टर से, ब्रॉडकास्ट ऐक्शन के बारे में पता चलता है. ये वे ऐक्शन होते हैं जिनके लिए रिसीवर ने सदस्यता ली है.

  2. BroadcastReceiver को सबक्लास करें और onReceive(Context, Intent) को लागू करें. यहां दिए गए उदाहरण में, ब्रॉडकास्ट रिसीवर ब्रॉडकास्ट के कॉन्टेंट को लॉग करता है और उसे दिखाता है:

    Kotlin

    class MyBroadcastReceiver : BroadcastReceiver() {
    
        @Inject
        lateinit var dataRepository: DataRepository
    
        override fun onReceive(context: Context, intent: Intent) {
            if (intent.action == "com.example.snippets.ACTION_UPDATE_DATA") {
                val data = intent.getStringExtra("com.example.snippets.DATA") ?: "No data"
                // Do something with the data, for example send it to a data repository:
                dataRepository.updateData(data)
            }
        }
    }
    

    Java

    public static class MyBroadcastReceiver extends BroadcastReceiver {
    
        @Inject
        DataRepository dataRepository;
    
        @Override
        public void onReceive(Context context, Intent intent) {
            if (Objects.equals(intent.getAction(), "com.example.snippets.ACTION_UPDATE_DATA")) {
                String data = intent.getStringExtra("com.example.snippets.DATA");
                // Do something with the data, for example send it to a data repository:
                if (data != null) { dataRepository.updateData(data); }
            }
        }
    }
    

ऐप्लिकेशन इंस्टॉल होने पर, सिस्टम पैकेज मैनेजर रिसीवर को रजिस्टर करता है. इसके बाद, रिसीवर आपके ऐप्लिकेशन में एक अलग एंट्री पॉइंट बन जाता है. इसका मतलब है कि अगर ऐप्लिकेशन चालू नहीं है, तो सिस्टम ऐप्लिकेशन को चालू करके ब्रॉडकास्ट डिलीवर कर सकता है.

सिस्टम, हर ब्रॉडकास्ट को मैनेज करने के लिए एक नया BroadcastReceiver कॉम्पोनेंट ऑब्जेक्ट बनाता है. यह ऑब्जेक्ट, सिर्फ़ onReceive(Context, Intent) को कॉल करने की अवधि के लिए मान्य होता है. जब आपका कोड इस तरीके से वापस आ जाता है, तो सिस्टम कॉम्पोनेंट को अब चालू नहीं मानता.

प्रोसेस की स्थिति पर असर

BroadcastReceiver के चालू या बंद होने से, इसमें मौजूद प्रोसेस पर असर पड़ता है. इससे सिस्टम को नुकसान पहुंचने की आशंका कम हो सकती है. फ़ोरग्राउंड प्रोसेस, रिसीवर के onReceive() तरीके को लागू करती है. सिस्टम, मेमोरी पर बहुत ज़्यादा दबाव पड़ने की स्थिति को छोड़कर, इस प्रोसेस को चलाता है.

सिस्टम, onReceive() के बाद BroadcastReceiver को बंद कर देता है. रिसीवर की होस्ट प्रोसेस की अहमियत, उसके ऐप्लिकेशन कॉम्पोनेंट पर निर्भर करती है. अगर उस प्रोसेस में सिर्फ़ मेनिफ़ेस्ट में बताया गया रिसीवर होस्ट किया जाता है, तो सिस्टम उसे onReceive() के बाद बंद कर सकता है, ताकि अन्य ज़रूरी प्रोसेस के लिए संसाधन खाली किए जा सकें. ऐसा उन ऐप्लिकेशन के लिए आम है जिनसे उपयोगकर्ता ने कभी इंटरैक्ट नहीं किया है या हाल ही में इंटरैक्ट नहीं किया है.

इसलिए, ब्रॉडकास्ट रिसीवर को बैकग्राउंड में लंबे समय तक चलने वाले थ्रेड शुरू नहीं करने चाहिए. सिस्टम, onReceive() के बाद किसी भी समय प्रोसेस को रोक सकता है, ताकि मेमोरी को वापस पाया जा सके. इससे, बनाई गई थ्रेड बंद हो जाती है. इस प्रोसेस को जारी रखने के लिए, JobScheduler का इस्तेमाल करके, पाने वाले के लिए JobService शेड्यूल करें, ताकि सिस्टम को पता चल सके कि प्रोसेस अब भी काम कर रही है. बैकग्राउंड में होने वाले काम की खास जानकारी में ज़्यादा जानकारी दी गई है.

ब्रॉडकास्ट भेजने की सुविधा

Android, ऐप्लिकेशन को ब्रॉडकास्ट भेजने के दो तरीके उपलब्ध कराता है:

  • sendOrderedBroadcast(Intent, String) तरीके से, एक बार में एक ही व्यक्ति को ब्रॉडकास्ट भेजे जाते हैं. हर रिसीवर एक-एक करके एक्ज़ीक्यूट होता है. इसलिए, यह अगले रिसीवर को नतीजा भेज सकता है. यह ब्रॉडकास्ट को पूरी तरह से बंद भी कर सकता है, ताकि यह अन्य डिवाइसों तक न पहुंचे. एक ही ऐप्लिकेशन प्रोसेस में रिसीवर के चलने के क्रम को कंट्रोल किया जा सकता है. इसके लिए, मिलते-जुलते इंटेंट-फ़िल्टर के android:priority एट्रिब्यूट का इस्तेमाल करें. एक जैसी प्राथमिकता वाले रिसीवर, किसी भी क्रम में चलाए जाते हैं.
  • sendBroadcast(Intent) तरीका, ब्रॉडकास्ट को सभी रिसीवर को किसी भी क्रम में भेजता है. इसे सामान्य ब्रॉडकास्ट कहा जाता है. यह ज़्यादा असरदार है, लेकिन इसका मतलब है कि मैसेज पाने वाले लोग, अन्य लोगों के नतीजे नहीं पढ़ सकते. साथ ही, ब्रॉडकास्ट से मिले डेटा को आगे नहीं बढ़ा सकते या ब्रॉडकास्ट को बंद नहीं कर सकते.

यहां दिए गए कोड स्निपेट में, Intent बनाकर और sendBroadcast(Intent) को कॉल करके ब्रॉडकास्ट भेजने का तरीका बताया गया है.

Kotlin

val intent = Intent("com.example.snippets.ACTION_UPDATE_DATA").apply {
    putExtra("com.example.snippets.DATA", newData)
    setPackage("com.example.snippets")
}
context.sendBroadcast(intent)

Java

Intent intent = new Intent("com.example.snippets.ACTION_UPDATE_DATA");
intent.putExtra("com.example.snippets.DATA", newData);
intent.setPackage("com.example.snippets");
context.sendBroadcast(intent);

ब्रॉडकास्ट मैसेज को Intent ऑब्जेक्ट में रैप किया जाता है. इंटेंट की action स्ट्रिंग में, ऐप्लिकेशन के Java पैकेज के नाम का सिंटैक्स होना चाहिए. साथ ही, यह ब्रॉडकास्ट इवेंट की यूनीक पहचान होनी चाहिए. putExtra(String, Bundle) का इस्तेमाल करके, इंटेंट में अतिरिक्त जानकारी अटैच की जा सकती है. किसी ब्रॉडकास्ट को एक ही संगठन के ऐप्लिकेशन के सेट तक सीमित किया जा सकता है. इसके लिए, इंटेंट पर setPackage(String) को कॉल करें.

अनुमतियों के ज़रिए ब्रॉडकास्ट पर पाबंदी लगाना

अनुमतियों की मदद से, ब्रॉडकास्ट को उन ऐप्लिकेशन तक सीमित किया जा सकता है जिनके पास कुछ अनुमतियां हैं. ब्रॉडकास्ट पाने वाले या भेजने वाले पर पाबंदियां लगाई जा सकती हैं.

अनुमतियों के साथ ब्रॉडकास्ट भेजना

sendBroadcast(Intent, String) या sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle) को कॉल करते समय, अनुमति पैरामीटर की जानकारी दी जा सकती है. सिर्फ़ वे डिवाइस ब्रॉडकास्ट पा सकते हैं जिन्होंने अपने मेनिफ़ेस्ट में <uses-permission> टैग के साथ अनुमति का अनुरोध किया है. अगर अनुमति खतरनाक है, तो आपको अनुमति देनी होगी. इसके बाद ही, ब्रॉडकास्ट पाने वाला व्यक्ति ब्रॉडकास्ट पा सकता है. उदाहरण के लिए, यह कोड अनुमति के साथ ब्रॉडकास्ट भेजता है:

Kotlin

context.sendBroadcast(intent, android.Manifest.permission.ACCESS_COARSE_LOCATION)

Java

context.sendBroadcast(intent, android.Manifest.permission.ACCESS_COARSE_LOCATION);

ब्रॉडकास्ट पाने के लिए, ऐप्लिकेशन को इस तरह अनुमति का अनुरोध करना होगा:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

आपके पास सिस्टम की मौजूदा अनुमति, जैसे कि BLUETOOTH_CONNECT तय करने का विकल्प होता है. इसके अलावा, <permission> एलिमेंट का इस्तेमाल करके, कस्टम अनुमति तय की जा सकती है. अनुमतियों और सुरक्षा के बारे में सामान्य जानकारी के लिए, सिस्टम की अनुमतियां देखें.

अनुमतियों के साथ ब्रॉडकास्ट पाना

अगर ब्रॉडकास्ट रिसीवर को रजिस्टर करते समय अनुमति का पैरामीटर तय किया जाता है (registerReceiver(BroadcastReceiver, IntentFilter, String, Handler) या मेनिफ़ेस्ट में <receiver> टैग के साथ), तो सिर्फ़ वे ब्रॉडकास्टर रिसीवर को इंटेंट भेज सकते हैं जिन्होंने अपने मेनिफ़ेस्ट में <uses-permission> टैग के साथ अनुमति का अनुरोध किया है. अगर अनुमति खतरनाक है, तो ब्रॉडकास्टर को भी अनुमति दी जानी चाहिए.

उदाहरण के लिए, मान लें कि आपके ऐप्लिकेशन में मेनिफ़ेस्ट में बताया गया रिसीवर इस तरह है:

<!-- If this receiver listens for broadcasts sent from the system or from
     other apps, even other apps that you own, set android:exported to "true". -->
<receiver
    android:name=".MyBroadcastReceiverWithPermission"
    android:permission="android.permission.ACCESS_COARSE_LOCATION"
    android:exported="true">
    <intent-filter>
        <action android:name="com.example.snippets.ACTION_UPDATE_DATA" />
    </intent-filter>
</receiver>

इसके अलावा, अगर आपका ऐप्लिकेशन कॉन्टेक्स्ट के हिसाब से रजिस्टर किए गए रिसीवर का इस्तेमाल करता है, तो ऐसा हो सकता है:

Kotlin

ContextCompat.registerReceiver(
    context, myBroadcastReceiver, filter,
    android.Manifest.permission.ACCESS_COARSE_LOCATION,
    null, // scheduler that defines thread, null means run on main thread
    receiverFlags
)

Java

ContextCompat.registerReceiver(
        context, myBroadcastReceiver, filter,
        android.Manifest.permission.ACCESS_COARSE_LOCATION,
        null, // scheduler that defines thread, null means run on main thread
        receiverFlags
);

इसके बाद, ब्रॉडकास्ट पाने वाले उन डिवाइसों पर ब्रॉडकास्ट भेजने के लिए, ब्रॉडकास्ट भेजने वाले ऐप्लिकेशन को इस तरह अनुमति का अनुरोध करना होगा:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

एक ही प्रोसेस में ब्रॉडकास्ट न करें

ब्रॉडकास्ट को इंटरप्रोसेस कम्यूनिकेशन (आईपीसी) के तौर पर डिज़ाइन किया गया है. इसकी मदद से, अलग-अलग ऐप्लिकेशन या सिस्टम और ऐप्लिकेशन के बीच मैसेज भेजे जा सकते हैं. सेल्फ़-ब्रॉडकास्ट भेजने का मतलब है कि ब्रॉडकास्ट पाने वाले सभी ऐप्लिकेशन, ब्रॉडकास्ट भेजने वाले ऐप्लिकेशन की प्रोसेस में ही चल रहे हैं. यह तरीका बहुत खराब है. इससे सिस्टम पर बेवजह का बोझ पड़ता है. इसलिए, ऐसा करने का सुझाव नहीं दिया जाता.

यहां दो सामान्य स्थितियां दी गई हैं, जिनमें ऐप्लिकेशन खुद को ब्रॉडकास्ट भेजते हैं:

  • एक ही प्रोसेस में कॉम्पोनेंट के बीच कम्यूनिकेट करना: उदाहरण के लिए, गतिविधियों, फ़्रैगमेंट, सेवाओं या बैकग्राउंड थ्रेड के बीच इवेंट या डेटा पास करना. ब्रॉडकास्ट भेजने के बजाय, प्रोसेस में मौजूद स्टैंडर्ड कम्यूनिकेशन मैकेनिज़्म का इस्तेमाल करें. जैसे, ऑब्ज़र्वर पैटर्न या रिएक्टिव स्ट्रीम:

    • Kotlin फ़्लो (SharedFlow और StateFlow): यह Kotlin में, इवेंट स्ट्रीम या स्टेट अपडेट को कोरूटीन और ऐप्लिकेशन के कॉम्पोनेंट में भेजने और देखने का आधुनिक और मुहावरेदार समाधान है.
    • शेयर किया गया ViewModel: इससे एक ही गतिविधि में अलग-अलग यूज़र इंटरफ़ेस (यूआई) कॉम्पोनेंट (जैसे कि फ़्रैगमेंट या कंपोज़ेबल) के बीच डेटा और इवेंट शेयर करने में आसानी होती है.
    • कॉल बैक और लिसनर: स्टैंडर्ड इंटरफ़ेस कॉल बैक या फ़ंक्शन रेफ़रंस, सीधे तौर पर कॉम्पोनेंट के बीच पास किए जाते हैं. इन्हें सेंट्रल रिपॉज़िटरी या कंट्रोलर के साथ रजिस्टर किया जाता है.
  • सिस्टम इवेंट, जॉब या अलार्म मैनेज करना: उदाहरण के लिए, शेड्यूल की गई जॉब, अलार्म या सिस्टम कॉलबैक पाना. इसके बाद, ब्रॉडकास्ट भेजकर असली काम को ट्रिगर करना. ब्रॉडकास्ट भेजने के बजाय, उस काम को सीधे तौर पर उस जॉब (जैसे कि JobService या WorkManager वर्कर), अलार्म हैंडलर या सिस्टम कॉलबैक कॉम्पोनेंट में पूरा करें. इसके अलावा, इसे सीधे तौर पर अपने ऐप्लिकेशन की कारोबारी नियम क्लास को सौंपें.

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

ऐप्लिकेशन कॉम्पोनेंट के बीच कम्यूनिकेशन डिज़ाइन करने के बारे में ज़्यादा जानने के लिए, ऐप्लिकेशन आर्किटेक्चर की गाइड देखें.

सुरक्षा से जुड़ी बातें

ब्रॉडकास्ट भेजने और पाने के लिए, सुरक्षा से जुड़ी कुछ बातों का ध्यान रखना ज़रूरी है:

  • अगर कई ऐप्लिकेशन ने अपने मेनिफ़ेस्ट में एक ही ब्रॉडकास्ट पाने के लिए रजिस्टर किया है, तो इससे सिस्टम कई ऐप्लिकेशन लॉन्च कर सकता है. इससे डिवाइस की परफ़ॉर्मेंस और उपयोगकर्ता अनुभव, दोनों पर काफ़ी असर पड़ सकता है. इससे बचने के लिए, मेनिफ़ेस्ट के एलान के बजाय कॉन्टेक्स्ट रजिस्ट्रेशन का इस्तेमाल करें. कभी-कभी, Android सिस्टम खुद ही कॉन्टेक्स्ट-रजिस्टर्ड रिसीवर का इस्तेमाल करने के लिए कहता है. उदाहरण के लिए, CONNECTIVITY_ACTION ब्रॉडकास्ट सिर्फ़ उन रिसीवर को डिलीवर किया जाता है जो कॉन्टेक्स्ट के साथ रजिस्टर किए गए हैं.

  • इंप्लिसिट इंटेंट का इस्तेमाल करके संवेदनशील जानकारी का प्रसारण न करें. अगर कोई ऐप्लिकेशन ब्रॉडकास्ट पाने के लिए रजिस्टर करता है, तो वह जानकारी को पढ़ सकता है. यह कंट्रोल करने के तीन तरीके हैं कि आपकी ब्रॉडकास्ट किसे मिलें:

    • ब्रॉडकास्ट भेजते समय, अनुमति तय की जा सकती है.
    • Android 4.0 (एपीआई लेवल 14) और इसके बाद के वर्शन में, ब्रॉडकास्ट भेजते समय setPackage(String) के साथ package तय किया जा सकता है. सिस्टम, ब्रॉडकास्ट को उन ऐप्लिकेशन तक सीमित रखता है जो पैकेज से मेल खाते हैं.
  • किसी रिसीवर को रजिस्टर करने पर, कोई भी ऐप्लिकेशन आपके ऐप्लिकेशन के रिसीवर को संभावित रूप से नुकसान पहुंचाने वाले ब्रॉडकास्ट भेज सकता है. आपके ऐप्लिकेशन को मिलने वाले ब्रॉडकास्ट को सीमित करने के कई तरीके हैं:

    • ब्रॉडकास्ट रिसीवर रजिस्टर करते समय, अनुमति दी जा सकती है.
    • मेनिफ़ेस्ट में बताए गए रिसीवर के लिए, मेनिफ़ेस्ट में android:exported एट्रिब्यूट को "false" पर सेट किया जा सकता है. ब्रॉडकास्ट पाने वाले व्यक्ति को, ऐप्लिकेशन के बाहर के सोर्स से ब्रॉडकास्ट नहीं मिलते.
  • ब्रॉडकास्ट की जाने वाली कार्रवाइयों के लिए नेमस्पेस ग्लोबल होता है. पक्का करें कि कार्रवाई के नाम और अन्य स्ट्रिंग, आपके मालिकाना हक वाले नेमस्पेस में लिखी गई हों. ऐसा न करने पर, हो सकता है कि आपका ऐप्लिकेशन अन्य ऐप्लिकेशन के साथ काम न करे.

  • क्योंकि रिसीवर का onReceive(Context, Intent) तरीका मुख्य थ्रेड पर चलता है, इसलिए इसे तुरंत लागू होना चाहिए और तुरंत जवाब देना चाहिए. अगर आपको लंबे समय तक चलने वाला कोई काम करना है, तो थ्रेड शुरू करते समय या बैकग्राउंड में चलने वाली सेवाओं को शुरू करते समय सावधानी बरतें. ऐसा इसलिए, क्योंकि onReceive() के वापस आने के बाद सिस्टम पूरी प्रोसेस को बंद कर सकता है. ज़्यादा जानकारी के लिए, प्रोसेस की स्थिति पर असर देखें. लंबे समय तक चलने वाले काम को पूरा करने के लिए, हमारा सुझाव है कि:

    • मैसेज पाने वाले व्यक्ति के onReceive() तरीके में goAsync() को कॉल करना और BroadcastReceiver.PendingResult को बैकग्राउंड थ्रेड में पास करना. इससे onReceive() से वापस आने के बाद भी ब्रॉडकास्ट चालू रहता है. हालांकि, इस तरीके से भी सिस्टम को उम्मीद होती है कि आप ब्रॉडकास्ट को बहुत कम समय (10 सेकंड से कम) में खत्म कर देंगे. इससे मुख्य थ्रेड में गड़बड़ी होने से बचाने के लिए, काम को किसी दूसरी थ्रेड पर ले जाया जा सकता है.
    • JobScheduler की मदद से कोई जॉब शेड्यूल करना. ज़्यादा जानकारी के लिए, इंटेलिजेंट जॉब शेड्यूलिंग देखें.
  • ब्रॉडकास्ट रिसीवर से गतिविधियां शुरू न करें, क्योंकि इससे उपयोगकर्ता अनुभव खराब होता है. ऐसा तब और ज़्यादा होता है, जब एक से ज़्यादा रिसीवर हों. इसके बजाय, सूचना दिखाने के बारे में सोचें.