बैकग्राउंड में चलने वाली प्रोसेस, मेमोरी और बैटरी का ज़्यादा इस्तेमाल कर सकती हैं. उदाहरण के लिए, चुपचाप होने वाला ब्रॉडकास्ट, बैकग्राउंड में कई प्रोसेस शुरू कर सकता है. ये प्रोसेस, ब्रॉडकास्ट को सुनने के लिए रजिस्टर की गई होती हैं. भले ही, ये प्रोसेस ज़्यादा काम न करती हों. इससे डिवाइस की परफ़ॉर्मेंस और उपयोगकर्ता अनुभव, दोनों पर काफ़ी असर पड़ सकता है.
इस समस्या को कम करने के लिए, Android 7.0 (एपीआई लेवल 24) ये पाबंदियां लगाता है:
- Android 7.0 (एपीआई लेवल 24) और उसके बाद के वर्शन को टारगेट करने वाले ऐप्लिकेशन को
CONNECTIVITY_ACTION
ब्रॉडकास्ट तब नहीं मिलते, जब वे मेनिफ़ेस्ट में अपने ब्रॉडकास्ट रिसीवर के बारे में बताते हैं. अगर ऐप्लिकेशन नेBroadcastReceiver
कोContext.registerReceiver()
के साथ रजिस्टर किया है और वह कॉन्टेक्स्ट अब भी मान्य है, तो ऐप्लिकेशन को अब भीCONNECTIVITY_ACTION
ब्रॉडकास्ट मिलते रहेंगे. - ऐप्लिकेशन,
ACTION_NEW_PICTURE
याACTION_NEW_VIDEO
ब्रॉडकास्ट नहीं भेज सकते या नहीं पा सकते. इस ऑप्टिमाइज़ेशन का असर, सिर्फ़ Android 7.0 (एपीआई लेवल 24) को टारगेट करने वाले ऐप्लिकेशन पर नहीं, बल्कि सभी ऐप्लिकेशन पर पड़ेगा.
अगर आपका ऐप्लिकेशन इनमें से किसी भी इंटेंट का इस्तेमाल करता है, तो आपको उन पर निर्भरता को जल्द से जल्द हटा देना चाहिए, ताकि आप Android 7.0 या उसके बाद के वर्शन वाले डिवाइसों को सही तरीके से टारगेट कर सकें. Android फ़्रेमवर्क, इन इम्प्लीसिट ब्रॉडकास्ट की ज़रूरत को कम करने के लिए कई समाधान उपलब्ध कराता है. उदाहरण के लिए, JobScheduler
और
नया WorkManager, नेटवर्क ऑपरेशन को शेड्यूल करने के लिए बेहतर तरीके उपलब्ध कराता है. ऐसा तब होता है, जब तय की गई शर्तें पूरी हो जाती हैं. जैसे, बिना शुल्क वाले नेटवर्क से कनेक्ट होना. अब कॉन्टेंट उपलब्ध कराने वाली कंपनियों में हुए बदलावों पर प्रतिक्रिया देने के लिए भी JobScheduler
का इस्तेमाल किया जा सकता है. JobInfo
ऑब्जेक्ट उन पैरामीटर को शामिल करते हैं जिनका इस्तेमाल JobScheduler
आपकी जॉब को शेड्यूल करने के लिए करता है. जब जॉब की शर्तें पूरी हो जाती हैं, तो सिस्टम आपके ऐप्लिकेशन के JobService
पर यह जॉब करता है.
इस पेज पर, हम JobScheduler
जैसे अन्य तरीकों का इस्तेमाल करने का तरीका जानेंगे, ताकि आपके ऐप्लिकेशन को इन नई पाबंदियों के मुताबिक बनाया जा सके.
उपयोगकर्ता की ओर से लगाई गई पाबंदियां
सिस्टम सेटिंग में मौजूद बैटरी खर्च पेज पर, उपयोगकर्ता इनमें से कोई विकल्प चुन सकता है:
- बिना पाबंदी के: बैकग्राउंड में सभी काम करने की अनुमति दें. इससे बैटरी ज़्यादा खर्च हो सकती है.
- ऑप्टिमाइज़ किया गया (डिफ़ॉल्ट): उपयोगकर्ता के ऐप्लिकेशन के साथ इंटरैक्ट करने के तरीके के आधार पर, बैकग्राउंड में काम करने की ऐप्लिकेशन की क्षमता को ऑप्टिमाइज़ करें.
- प्रतिबंधित: इससे ऐप्लिकेशन को बैकग्राउंड में चलने से पूरी तरह रोक दिया जाता है. ऐसा हो सकता है कि ऐप्लिकेशन ठीक से काम न करें.
अगर कोई ऐप्लिकेशन, Android के मुख्य फ़ंक्शन में बताए गए गलत व्यवहारों को दिखाता है, तो सिस्टम उपयोगकर्ता को उस ऐप्लिकेशन के सिस्टम संसाधनों के ऐक्सेस पर पाबंदी लगाने के लिए कह सकता है.
अगर सिस्टम को पता चलता है कि कोई ऐप्लिकेशन ज़्यादा संसाधनों का इस्तेमाल कर रहा है, तो वह उपयोगकर्ता को इसकी सूचना देता है. साथ ही, उपयोगकर्ता को ऐप्लिकेशन की कार्रवाइयों पर पाबंदी लगाने का विकल्प भी देता है. इन वजहों से सूचना मिल सकती है:
- वेक लॉक का ज़्यादा इस्तेमाल: स्क्रीन बंद होने पर, एक घंटे तक एक पार्शियल वेक लॉक का इस्तेमाल किया गया
- बैकग्राउंड में काम करने वाली ज़्यादा सेवाएं: अगर ऐप्लिकेशन, 26 से पहले के एपीआई लेवल को टारगेट करता है और इसमें बैकग्राउंड में काम करने वाली ज़्यादा सेवाएं हैं
डिवाइस बनाने वाली कंपनी, पाबंदियों की सटीक जानकारी तय करती है. उदाहरण के लिए, Android 9 (एपीआई लेवल 28) या उसके बाद के वर्शन पर काम करने वाले AOSP बिल्ड में, बैकग्राउंड में चल रहे "प्रतिबंधित" ऐप्लिकेशन पर ये पाबंदियां लागू होती हैं:
- फ़ोरग्राउंड सेवाएं लॉन्च नहीं की जा सकतीं
- मौजूदा फ़ोरग्राउंड सेवाओं को फ़ोरग्राउंड से हटा दिया जाता है
- अलार्म ट्रिगर नहीं हो रहे हैं
- जॉब लागू नहीं होते
इसके अलावा, अगर कोई ऐप्लिकेशन Android 13 (एपीआई लेवल 33) या उसके बाद के वर्शन को टारगेट करता है और उसकी स्थिति "प्रतिबंधित" है, तो सिस्टम BOOT_COMPLETED
ब्रॉडकास्ट या LOCKED_BOOT_COMPLETED
ब्रॉडकास्ट तब तक डिलीवर नहीं करता, जब तक कि ऐप्लिकेशन को किसी और वजह से शुरू नहीं किया जाता.
इन पाबंदियों के बारे में ज़्यादा जानने के लिए, पावर मैनेजमेंट से जुड़ी पाबंदियां लेख पढ़ें.
नेटवर्क गतिविधि के ब्रॉडकास्ट पाने से जुड़ी पाबंदियां
Android 7.0 (एपीआई लेवल 24) को टारगेट करने वाले ऐप्लिकेशन को CONNECTIVITY_ACTION
ब्रॉडकास्ट तब नहीं मिलते, जब वे अपने मेनिफ़ेस्ट में उन्हें पाने के लिए रजिस्टर करते हैं. साथ ही, इस ब्रॉडकास्ट पर निर्भर प्रोसेस शुरू नहीं होंगी. इससे उन ऐप्लिकेशन को समस्या हो सकती है जो नेटवर्क में होने वाले बदलावों को सुनना चाहते हैं या डिवाइस के बिना शुल्क वाले नेटवर्क से कनेक्ट होने पर, नेटवर्क पर ज़्यादा गतिविधियां करना चाहते हैं. इस पाबंदी से बचने के लिए, Android फ़्रेमवर्क में पहले से ही कई समाधान मौजूद हैं. हालांकि, सही समाधान चुनना इस बात पर निर्भर करता है कि आपको अपने ऐप्लिकेशन से क्या हासिल करना है.
ध्यान दें: Context.registerReceiver()
के साथ रजिस्टर किए गए BroadcastReceiver
को, ऐप्लिकेशन के चलने के दौरान ये ब्रॉडकास्ट मिलते रहेंगे.
बिना मेज़र किए जाने वाले कनेक्शन पर नेटवर्क जॉब शेड्यूल करना
JobInfo
ऑब्जेक्ट बनाने के लिए JobInfo.Builder
क्लास का इस्तेमाल करते समय, setRequiredNetworkType()
तरीका लागू करें और JobInfo.NETWORK_TYPE_UNMETERED
को जॉब पैरामीटर के तौर पर पास करें. यहां दिया गया कोड सैंपल, किसी सेवा को तब चलने के लिए शेड्यूल करता है, जब डिवाइस किसी ऐसे नेटवर्क से कनेक्ट हो जो मीटर के हिसाब से शुल्क नहीं लेता और चार्ज हो रहा हो:
Kotlin
const val MY_BACKGROUND_JOB = 0 ... fun scheduleJob(context: Context) { val jobScheduler = context.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler val job = JobInfo.Builder( MY_BACKGROUND_JOB, ComponentName(context, MyJobService::class.java) ) .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED) .setRequiresCharging(true) .build() jobScheduler.schedule(job) }
Java
public static final int MY_BACKGROUND_JOB = 0; ... public static void scheduleJob(Context context) { JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); JobInfo job = new JobInfo.Builder( MY_BACKGROUND_JOB, new ComponentName(context, MyJobService.class)) .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED) .setRequiresCharging(true) .build(); js.schedule(job); }
जब आपकी जॉब की शर्तें पूरी हो जाती हैं, तो आपके ऐप्लिकेशन को एक कॉलबैक मिलता है. इससे, तय किए गए JobService.class
में onStartJob()
तरीका चलाया जा सकता है. JobScheduler
को लागू करने के और उदाहरण देखने के लिए, JobScheduler का सैंपल ऐप्लिकेशन देखें.
JobScheduler का नया विकल्प, WorkManager है. यह एक ऐसा एपीआई है जिसकी मदद से, बैकग्राउंड में ऐसे टास्क शेड्यूल किए जा सकते हैं जिन्हें पूरा करना ज़रूरी है. भले ही, ऐप्लिकेशन प्रोसेस चल रही हो या नहीं. डिवाइस के एपीआई लेवल जैसे फ़ैक्टर के आधार पर, WorkManager, टास्क को चलाने का सही तरीका चुनता है. जैसे, सीधे तौर पर आपके ऐप्लिकेशन प्रोसेस में किसी थ्रेड पर या फिर JobScheduler, FirebaseJobDispatcher या AlarmManager का इस्तेमाल करके. इसके अलावा, WorkManager के लिए Play services की ज़रूरत नहीं होती. साथ ही, यह कई ऐडवांस सुविधाएं भी उपलब्ध कराता है. जैसे, टास्क को एक साथ जोड़ना या किसी टास्क का स्टेटस देखना. ज़्यादा जानने के लिए, WorkManager देखें.
ऐप्लिकेशन के चलने के दौरान, इंटरनेट कनेक्टिविटी पर नज़र रखना
चल रहे ऐप्लिकेशन, अब भी रजिस्टर किए गए BroadcastReceiver
की मदद से CONNECTIVITY_CHANGE
को सुन सकते हैं. हालांकि, ConnectivityManager
एपीआई, कॉलबैक का अनुरोध करने के लिए एक बेहतर तरीका उपलब्ध कराता है. यह तरीका सिर्फ़ तब काम करता है, जब नेटवर्क से जुड़ी तय शर्तें पूरी होती हैं.
NetworkRequest
ऑब्जेक्ट, NetworkCapabilities
के हिसाब से नेटवर्क कॉलबैक के पैरामीटर तय करते हैं. आपने
NetworkRequest.Builder
क्लास की मदद से NetworkRequest
ऑब्जेक्ट बनाए हैं. registerNetworkCallback()
इसके बाद, NetworkRequest
ऑब्जेक्ट को सिस्टम को पास करता है. नेटवर्क की शर्तें पूरी होने पर, ऐप्लिकेशन को एक कॉलबैक मिलता है. इससे, ऐप्लिकेशन अपनी ConnectivityManager.NetworkCallback
क्लास में बताए गए onAvailable()
तरीके को लागू कर पाता है.
ऐप्लिकेशन को तब तक कॉलबैक मिलते रहेंगे, जब तक वह बंद नहीं हो जाता या unregisterNetworkCallback()
को कॉल नहीं करता.
इमेज और वीडियो ब्रॉडकास्ट पाने से जुड़ी पाबंदियां
Android 7.0 (एपीआई लेवल 24) में, ऐप्लिकेशन ACTION_NEW_PICTURE
या ACTION_NEW_VIDEO
ब्रॉडकास्ट नहीं भेज या पा सकते. इस पाबंदी से, नई इमेज या वीडियो को प्रोसेस करने के लिए, कई ऐप्लिकेशन के चालू होने पर, परफ़ॉर्मेंस और उपयोगकर्ता अनुभव पर पड़ने वाले असर को कम करने में मदद मिलती है. Android 7.0 (एपीआई लेवल 24)
में, JobInfo
और JobParameters
को बेहतर बनाया गया है, ताकि कोई दूसरा समाधान दिया जा सके.
कॉन्टेंट यूआरआई में बदलाव होने पर जॉब ट्रिगर करना
कॉन्टेंट यूआरआई में बदलाव होने पर जॉब ट्रिगर करने के लिए, Android 7.0 (एपीआई लेवल 24) ने JobInfo
एपीआई को इन तरीकों से बेहतर बनाया है:
-
JobInfo.TriggerContentUri()
- कॉन्टेंट यूआरआई में बदलाव होने पर, जॉब को ट्रिगर करने के लिए ज़रूरी पैरामीटर को शामिल करता है.
-
JobInfo.Builder.addTriggerContentUri()
-
TriggerContentUri
ऑब्जेक्ट कोJobInfo
में पास करता है.ContentObserver
एन्कैप्सुलेट किए गए कॉन्टेंट के यूआरआई पर नज़र रखता है. अगर किसी नौकरी से जुड़े एक से ज़्यादाTriggerContentUri
ऑब्जेक्ट हैं, तो सिस्टम एक कॉलबैक उपलब्ध कराता है. भले ही, वह कॉन्टेंट के सिर्फ़ एक यूआरआई में हुए बदलाव की रिपोर्ट करता हो. -
TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS
फ़्लैग जोड़ें, ताकि दिए गए यूआरआई के किसी वंश में बदलाव होने पर, जॉब ट्रिगर हो सके. यह फ़्लैगregisterContentObserver()
फ़ंक्शन में इस्तेमाल किए गएnotifyForDescendants
पैरामीटर से जुड़ा होता है.
ध्यान दें: TriggerContentUri()
का इस्तेमाल,
setPeriodic()
या setPersisted()
के साथ नहीं किया जा सकता. कॉन्टेंट में होने वाले बदलावों पर लगातार नज़र रखने के लिए, ऐप्लिकेशन के JobService
के सबसे हाल के कॉलबैक को मैनेज करने के खत्म होने से पहले, नया JobInfo
शेड्यूल करें.
यहां दिया गया सैंपल कोड, एक जॉब को शेड्यूल करता है, ताकि जब सिस्टम, कॉन्टेंट के यूआरआई MEDIA_URI
में बदलाव की सूचना दे, तो वह जॉब ट्रिगर हो जाए:
Kotlin
const val MY_BACKGROUND_JOB = 0 ... fun scheduleJob(context: Context) { val jobScheduler = context.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler val job = JobInfo.Builder( MY_BACKGROUND_JOB, ComponentName(context, MediaContentJob::class.java) ) .addTriggerContentUri( JobInfo.TriggerContentUri( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS ) ) .build() jobScheduler.schedule(job) }
Java
public static final int MY_BACKGROUND_JOB = 0; ... public static void scheduleJob(Context context) { JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); JobInfo.Builder builder = new JobInfo.Builder( MY_BACKGROUND_JOB, new ComponentName(context, MediaContentJob.class)); builder.addTriggerContentUri( new JobInfo.TriggerContentUri(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS)); js.schedule(builder.build()); }
जब सिस्टम, बताए गए कॉन्टेंट यूआरआई में बदलाव की सूचना देता है, तो आपके ऐप्लिकेशन को कॉलबैक मिलता है और JobParameters
ऑब्जेक्ट को MediaContentJob.class
में onStartJob()
तरीके में पास किया जाता है.
यह पता लगाना कि कॉन्टेंट की किन संस्थाओं ने कोई जॉब ट्रिगर किया
Android 7.0 (एपीआई लेवल 24) में JobParameters
को भी शामिल किया गया है, ताकि आपके ऐप्लिकेशन को इस बारे में काम की जानकारी मिल सके कि किन कॉन्टेंट अथॉरिटी और यूआरआई ने जॉब को ट्रिगर किया:
-
Uri[] getTriggeredContentUris()
-
उन यूआरआई की सूची दिखाता है जिन्होंने जॉब को ट्रिगर किया है. अगर किसी यूआरआई ने जॉब को ट्रिगर नहीं किया है (उदाहरण के लिए, जॉब को समयसीमा या किसी दूसरी वजह से ट्रिगर किया गया था) या बदले गए यूआरआई की संख्या 50 से ज़्यादा है, तो यह
null
होगा. -
String[] getTriggeredContentAuthorities()
-
यह उन कॉन्टेंट अथॉरिटी की स्ट्रिंग का अरे दिखाता है जिन्होंने जॉब को ट्रिगर किया है.
अगर दिखाया गया कलेक्शन
null
नहीं है, तोgetTriggeredContentUris()
का इस्तेमाल करके, उन यूआरआई की जानकारी पाएं जिनमें बदलाव हुआ है.
यहां दिया गया सैंपल कोड, JobService.onStartJob()
तरीके को बदल देता है और
उन कॉन्टेंट अथॉरिटी और यूआरआई को रिकॉर्ड करता है जिन्होंने जॉब को ट्रिगर किया है:
Kotlin
override fun onStartJob(params: JobParameters): Boolean { StringBuilder().apply { append("Media content has changed:\n") params.triggeredContentAuthorities?.also { authorities -> append("Authorities: ${authorities.joinToString(", ")}\n") append(params.triggeredContentUris?.joinToString("\n")) } ?: append("(No content)") Log.i(TAG, toString()) } return true }
Java
@Override public boolean onStartJob(JobParameters params) { StringBuilder sb = new StringBuilder(); sb.append("Media content has changed:\n"); if (params.getTriggeredContentAuthorities() != null) { sb.append("Authorities: "); boolean first = true; for (String auth : params.getTriggeredContentAuthorities()) { if (first) { first = false; } else { sb.append(", "); } sb.append(auth); } if (params.getTriggeredContentUris() != null) { for (Uri uri : params.getTriggeredContentUris()) { sb.append("\n"); sb.append(uri); } } } else { sb.append("(No content)"); } Log.i(TAG, sb.toString()); return true; }
अपने ऐप्लिकेशन को और ऑप्टिमाइज़ करना
अपने ऐप्लिकेशन को कम मेमोरी वाले डिवाइसों पर या कम मेमोरी वाली स्थितियों में चलाने के लिए ऑप्टिमाइज़ करने से, परफ़ॉर्मेंस और उपयोगकर्ता अनुभव को बेहतर बनाया जा सकता है. बैकग्राउंड सेवाओं और मेनिफ़ेस्ट में रजिस्टर किए गए, डिफ़ॉल्ट तौर पर चालू रहने वाले ब्रॉडकास्ट रिसीवर पर निर्भरता हटाने से, आपके ऐप्लिकेशन को ऐसे डिवाइसों पर बेहतर तरीके से काम करने में मदद मिल सकती है. हालांकि, Android 7.0 (एपीआई लेवल 24) में इनमें से कुछ समस्याओं को कम करने के लिए कदम उठाए गए हैं, लेकिन हमारा सुझाव है कि आप अपने ऐप्लिकेशन को ऑप्टिमाइज़ करें, ताकि वह इन बैकग्राउंड प्रोसेस का इस्तेमाल किए बिना ही काम कर सके.
Android डीबग ब्रिज (ADB) के इन कमांड की मदद से, बैकग्राउंड प्रोसेस बंद होने पर ऐप्लिकेशन के व्यवहार की जांच की जा सकती है:
- ऐसी स्थितियों को सिम्युलेट करने के लिए जहां डिफ़ॉल्ट ब्रॉडकास्ट और बैकग्राउंड सेवाएं उपलब्ध नहीं हैं, यह कमांड डालें:
-
$ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND ignore
- इंप्लिसिट ब्रॉडकास्ट और बैकग्राउंड सेवाओं को फिर से चालू करने के लिए, यह कमांड डालें:
-
$ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND allow
- बैकग्राउंड में बैटरी इस्तेमाल करने के लिए, उपयोगकर्ता के आपके ऐप्लिकेशन को "पाबंदी वाला" स्टेटस देने का अनुकरण किया जा सकता है. इस सेटिंग की मदद से, आपके ऐप्लिकेशन को बैकग्राउंड में चलने से रोका जा सकता है. ऐसा करने के लिए, टर्मिनल विंडो में यह कमांड चलाएं:
-
$ adb shell cmd appops set <PACKAGE_NAME> RUN_ANY_IN_BACKGROUND deny