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 कॉन्टेक्स्ट में रजिस्टर किया है, तो आपको ब्रॉडकास्ट तब तक मिलते हैं, जब तक गतिविधि
चालू रहती है. अगर आपने ऐप्लिकेशन कॉन्टेक्स्ट के साथ रजिस्टर किया है, तो आपको ब्रॉडकास्ट तब तक मिलते हैं, जब तक ऐप्लिकेशन चलता है.
किसी कॉन्टेक्स्ट के साथ रिसीवर रजिस्टर करने के लिए, यह तरीका अपनाएं:
अपने ऐप्लिकेशन के मॉड्यूल-लेवल की बिल्ड फ़ाइल में, AndroidX Core लाइब्रेरी का 1.9.0 या इसके बाद का वर्शन शामिल करें: AndroidX Core लाइब्रेरी:
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") }
BroadcastReceiverका इंस्टेंस बनाएं:Kotlin
val myBroadcastReceiver = MyBroadcastReceiver()Java
MyBroadcastReceiver myBroadcastReceiver = new MyBroadcastReceiver();IntentFilterका इंस्टेंस बनाएं:Kotlin
val filter = IntentFilter("com.example.snippets.ACTION_UPDATE_DATA")Java
IntentFilter filter = new IntentFilter("com.example.snippets.ACTION_UPDATE_DATA");चुनें कि ब्रॉडकास्ट रिसीवर को एक्सपोर्ट किया जाना चाहिए या नहीं. साथ ही, यह भी चुनें कि यह डिवाइस पर मौजूद अन्य ऐप्लिकेशन को दिखना चाहिए या नहीं. अगर यह रिसीवर, सिस्टम या अन्य ऐप्लिकेशन से भेजे गए ब्रॉडकास्ट को सुन रहा है, तो
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;registerReceiver()को कॉल करके, रिसीवर रजिस्टर करें:Kotlin
ContextCompat.registerReceiver(context, myBroadcastReceiver, filter, receiverFlags)Java
ContextCompat.registerReceiver(context, myBroadcastReceiver, filter, receiverFlags);ब्रॉडकास्ट पाना बंद करने के लिए, कॉल करें
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
}
मेनिफ़ेस्ट में एलान किए गए रिसीवर
अगर आपने अपने मेनिफ़ेस्ट में ब्रॉडकास्ट रिसीवर का एलान किया है, तो ब्रॉडकास्ट भेजे जाने पर, सिस्टम आपका ऐप्लिकेशन लॉन्च करता है. अगर ऐप्लिकेशन पहले से नहीं चल रहा है, तो सिस्टम ऐप्लिकेशन लॉन्च करता है.
मेनिफ़ेस्ट में ब्रॉडकास्ट रिसीवर का एलान करने के लिए, यह तरीका अपनाएं:
अपने ऐप्लिकेशन के मेनिफ़ेस्ट में,
<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>इंटेंट फ़िल्टर, उन ब्रॉडकास्ट ऐक्शन की जानकारी देते हैं जिनके लिए आपका रिसीवर सदस्यता लेता है.
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 काम कर रहा है या नहीं, इससे उसकी contained
process पर असर पड़ता है. इससे सिस्टम के उसे बंद करने की संभावना बदल सकती है. फ़ोरग्राउंड प्रोसेस
रिसीवर के onReceive() तरीके को लागू करती है. सिस्टम, प्रोसेस को तब तक चलाता है, जब तक मेमोरी पर बहुत ज़्यादा दबाव न हो.
सिस्टम, onReceive() के बाद BroadcastReceiver को डीऐक्टिवेट कर देता है.
रिसीवर की होस्ट प्रोसेस की अहमियत, उसके ऐप्लिकेशन कॉम्पोनेंट पर निर्भर करती है. अगर उस प्रोसेस में सिर्फ़ मेनिफ़ेस्ट में एलान किया गया रिसीवर होस्ट किया जाता है, तो सिस्टम, onReceive() के बाद उसे बंद कर सकता है, ताकि अन्य ज़्यादा ज़रूरी प्रोसेस के लिए संसाधन खाली किए जा सकें. ऐसा आम तौर पर उन ऐप्लिकेशन के लिए होता है जिनसे उपयोगकर्ता ने कभी इंटरैक्ट नहीं किया है या हाल ही में इंटरैक्ट नहीं किया है.
इसलिए, ब्रॉडकास्ट रिसीवर को बैकग्राउंड में लंबे समय तक चलने वाली थ्रेड शुरू नहीं करनी चाहिए.
सिस्टम, मेमोरी वापस पाने के लिए, onReceive() के बाद किसी भी समय प्रोसेस को बंद कर सकता है. इससे बनाई गई थ्रेड खत्म हो जाती है. प्रोसेस को चालू रखने के लिए, रिसीवर से
JobService शेड्यूल करें, ताकि JobScheduler सिस्टम को पता चले कि प्रोसेस अब भी काम कर रही है. ज़्यादा जानकारी के लिए, बैकग्राउंड में काम करने की सुविधा की खास जानकारी
देखें.
ब्रॉडकास्ट भेजना
Android, ऐप्लिकेशन को ब्रॉडकास्ट भेजने के दो तरीके उपलब्ध कराता है:
- The
sendOrderedBroadcast(Intent, String)तरीका, एक बार में एक रिसीवर को ब्रॉडकास्ट भेजता है. हर रिसीवर बारी-बारी से काम करता है. इसलिए, यह नतीजे को अगले रिसीवर तक पहुंचा सकता है. यह ब्रॉडकास्ट को पूरी तरह से रद्द भी कर सकता है, ताकि यह अन्य रिसीवर तक न पहुंचे. आपके पास एक ही ऐप्लिकेशन प्रोसेस में, रिसीवर के चलने के क्रम को कंट्रोल करने का विकल्प होता है. ऐसा करने के लिए, मैचिंग इंटेंट-फ़िल्टर केandroid:priorityएट्रिब्यूट का इस्तेमाल करें. एक ही प्राथमिकता वाले रिसीवर, किसी भी क्रम में चलते हैं. - The
sendBroadcast(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>` एलिमेंट की मदद से, कस्टम अनुमति तय की जा सकती है.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 में, कोरूटीन और आपके ऐप्लिकेशन में मौजूद कॉम्पोनेंट के बीच, इवेंट स्ट्रीम या स्टेट अपडेट को एमिट और ऑब्ज़र्व करने के लिए, यह एक आधुनिक, मुहावरेदार समाधान है. - Shared
ViewModel: एक ही गतिविधि में, अलग-अलग यूज़र इंटरफ़ेस कॉम्पोनेंट (जैसे, फ़्रैगमेंट या कंपोज़ेबल) के बीच डेटा और इवेंट शेयर करने में मदद करता है. - कॉलबैक और लिसनर: स्टैंडर्ड इंटरफ़ेस कॉल बैक या फ़ंक्शन रेफ़रंस, कॉम्पोनेंट के बीच सीधे तौर पर पास किए जाते हैं या किसी सेंट्रल रिपॉज़िटरी या कंट्रोलर के साथ रजिस्टर किए जाते हैं.
- Kotlin फ़्लो (
सिस्टम इवेंट, जॉब या अलार्म हैंडल करना: उदाहरण के लिए, शेड्यूल किया गया जॉब, अलार्म या सिस्टम कॉल बैक पाना. इसके बाद, असल काम को ट्रिगर करने के लिए ब्रॉडकास्ट भेजना. ब्रॉडकास्ट भेजने के बजाय, उस जॉब (जैसे,
JobServiceया WorkManager वर्कर), अलार्म हैंडलर या सिस्टम कॉलबैक कॉम्पोनेंट में सीधे तौर पर काम पूरा करें या सीधे अपने ऐप्लिकेशन की कारोबारी नियम क्लास को डेलिगेट करें.
Android 17 QPR2 या इसके बाद के वर्शन पर चलने वाले डिवाइसों पर, सिस्टम सेल्फ़-ब्रॉडकास्ट को ज़्यादा कारगर तरीके से डिलीवर करता है. इसके लिए, वह उन्हें भेजने वाली प्रोसेस पर वापस भेजता है. यह प्रोसेस, उन्हें मुख्य थ्रेड पर अपने रिसीवर को डिलीवर करती है. सेल्फ़-ब्रॉडकास्ट भेजने से, आपकी प्रोसेस की अहमियत नहीं बढ़ती. साथ ही, कैश मेमोरी में सेव की गई प्रोसेस को फ़्रीज़ होने से नहीं रोका जा सकता. इसलिए, अपने ऐप्लिकेशन को चालू रखने या बैकग्राउंड में काम करने के लिए, सेल्फ़-ब्रॉडकास्ट पर भरोसा न करें. इसके बजाय, अपने टास्क के लिए सही एपीआई चुनें. इसके बारे में, बैकग्राउंड में काम करने की सुविधा की खास जानकारी में बताया गया है. इस ऑप्टिमाइज़ेशन के बावजूद, सेल्फ़-ब्रॉडकास्ट, इन-प्रोसेस कम्यूनिकेशन मैकेनिज़्म की तुलना में कम कारगर होते हैं. इसलिए, इनके बजाय उन विकल्पों का इस्तेमाल करें.
ऐप्लिकेशन कॉम्पोनेंट के बीच कम्यूनिकेशन डिज़ाइन करने के बारे में ज़्यादा जानने के लिए, ऐप्लिकेशन आर्किटेक्चर के लिए गाइड देखें.
सुरक्षा से जुड़ी बातें
ब्रॉडकास्ट भेजने और पाने के लिए, सुरक्षा से जुड़ी कुछ बातें यहां दी गई हैं:
अगर कई ऐप्लिकेशन ने अपने मेनिफ़ेस्ट में एक ही ब्रॉडकास्ट पाने के लिए रजिस्टर किया है, तो इससे सिस्टम कई ऐप्लिकेशन लॉन्च कर सकता है. इससे डिवाइस की परफ़ॉर्मेंस और उपयोगकर्ता अनुभव, दोनों पर काफ़ी असर पड़ सकता है. इससे बचने के लिए, मेनिफ़ेस्ट में एलान करने के बजाय, कॉन्टेक्स्ट रजिस्ट्रेशन का इस्तेमाल करें. कभी-कभी, Android सिस्टम खुद ही कॉन्टेक्स्ट-रजिस्टर्ड रिसीवर के इस्तेमाल को लागू करता है. उदाहरण के लिए,
CONNECTIVITY_ACTIONब्रॉडकास्ट सिर्फ़ कॉन्टेक्स्ट-रजिस्टर्ड रिसीवर को डिलीवर किया जाता है.इंप्लिसिट इंटेंट का इस्तेमाल करके, संवेदनशील जानकारी ब्रॉडकास्ट न करें. अगर कोई ऐप्लिकेशन, ब्रॉडकास्ट पाने के लिए रजिस्टर करता है, तो वह जानकारी पढ़ सकता है. यह कंट्रोल करने के तीन तरीके हैं कि आपके ब्रॉडकास्ट कौन पा सकता है:
- ब्रॉडकास्ट भेजते समय, अनुमति तय की जा सकती है.
- Android 4.0 (एपीआई लेवल 14) और इसके बाद के वर्शन में, ब्रॉडकास्ट भेजते समय,
setPackage(String)की मदद से पैकेज तय किया जा सकता है. सिस्टम, ब्रॉडकास्ट को उन ऐप्लिकेशन के सेट तक सीमित करता है जो पैकेज से मैच करते हैं.
रिसीवर रजिस्टर करने पर, कोई भी ऐप्लिकेशन आपके ऐप्लिकेशन के रिसीवर को संभावित तौर पर नुकसान पहुंचाने वाले ब्रॉडकास्ट भेज सकता है. आपके ऐप्लिकेशन को मिलने वाले ब्रॉडकास्ट को सीमित करने के कई तरीके हैं:
- ब्रॉडकास्ट रिसीवर रजिस्टर करते समय, अनुमति तय की जा सकती है.
- मेनिफ़ेस्ट में एलान किए गए रिसीवर के लिए, मेनिफ़ेस्ट में android:exported एट्रिब्यूट को "false" पर सेट किया जा सकता है. रिसीवर को ऐप्लिकेशन के बाहर के सोर्स से ब्रॉडकास्ट नहीं मिलते.
ब्रॉडकास्ट ऐक्शन के लिए नेमस्पेस ग्लोबल होता है. पक्का करें कि ऐक्शन के नाम और अन्य स्ट्रिंग, आपके नेमस्पेस में लिखी गई हों. ऐसा न करने पर, अन्य ऐप्लिकेशन के साथ अनजाने में टकराव हो सकता है.
रिसीवर का
onReceive(Context, Intent)तरीका, मुख्य थ्रेड पर चलता है. इसलिए, इसे तेज़ी से लागू किया जाना चाहिए और तेज़ी से वापस आना चाहिए. अगर आपको लंबे समय तक चलने वाला काम करना है, तो थ्रेड स्पॉन करने या बैकग्राउंड में चलने वाली सेवाएं शुरू करने के बारे में सावधानी बरतें, क्योंकि सिस्टम,onReceive()के वापस आने के बाद पूरी प्रोसेस को बंद कर सकता है. ज़्यादा जानकारी के लिए, प्रोसेस की स्थिति पर असर देखें. लंबे समय तक चलने वाला काम करने के लिए, हमारा सुझाव है कि:- अपने रिसीवर के
onReceive()तरीके मेंgoAsync()को कॉल करें औरBroadcastReceiver.PendingResultको बैकग्राउंड थ्रेड पर पास करें. इससेonReceive()से वापस आने के बाद भी ब्रॉडकास्ट चालू रहता है. हालांकि, इस तरीके के बावजूद, सिस्टम आपसे ब्रॉडकास्ट को बहुत तेज़ी से (10 सेकंड के अंदर) खत्म करने की उम्मीद करता है. यह आपको मुख्य थ्रेड में गड़बड़ी से बचने के लिए, काम को किसी दूसरी थ्रेड पर ले जाने की अनुमति देता है. JobSchedulerकी मदद से, जॉब शेड्यूल करना. ज़्यादा जानकारी के लिए, देखें स्मार्ट तरीके से जॉब शेड्यूल करना.
- अपने रिसीवर के
ब्रॉडकास्ट रिसीवर से गतिविधियां शुरू न करें, क्योंकि इससे उपयोगकर्ता अनुभव खराब होता है. खास तौर पर, तब जब एक से ज़्यादा रिसीवर हों. इसके बजाय, सूचना दिखाने पर विचार करें.