बैकग्राउंड ऑप्टिमाइज़ेशन

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

इस समस्या को कम करने के लिए, Android 7.0 (एपीआई लेवल 24) ये चीज़ें लागू करता है प्रतिबंध:

  • Android 7.0 (एपीआई लेवल 24) और उसके बाद के वर्शन को टारगेट करने वाले ऐप्लिकेशन को CONNECTIVITY_ACTION ब्रॉडकास्ट करता है, अगर वे मेनिफ़ेस्ट में अपने ब्रॉडकास्ट रिसीवर की जानकारी दें. ऐप्लिकेशन अब भी रजिस्टर होने पर CONNECTIVITY_ACTION ब्रॉडकास्ट पाएं Context.registerReceiver() के साथ उसकी BroadcastReceiver और वह संदर्भ अब भी मान्य है.
  • ऐप्लिकेशन, 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) या उसके बाद के वर्शन पर चलने वाले एओएसपी बिल्ड पर, ऐप्लिकेशन बैकग्राउंड में चल रहे हों, जो "पाबंदी लगी हैं" वाली स्थिति में हों राज्यों के लिए ये ज़रूरी हैं सीमाएं:

  • फ़ोरग्राउंड सेवाएं लॉन्च नहीं की जा सकीं
  • फ़ोरग्राउंड से जुड़ी मौजूदा सेवाओं को हटा दिया गया है
  • अलार्म ट्रिगर नहीं किए गए हैं
  • जॉब नहीं चलाए जाते

साथ ही, अगर कोई ऐप्लिकेशन Android 13 (एपीआई लेवल 33) या उसके बाद वाले वर्शन को टारगेट करता है और "प्रतिबंधित" की स्थिति हो सकती है, तो सिस्टम BOOT_COMPLETED पर ब्रॉडकास्ट नहीं करता है या अन्य के लिए ऐप्लिकेशन शुरू होने तक LOCKED_BOOT_COMPLETED का ब्रॉडकास्ट की वजह.

खास पाबंदियों की जानकारी यहां दी गई है पावर मैनेजमेंट से जुड़ी पाबंदियां.

नेटवर्क गतिविधि के ब्रॉडकास्ट पाने से जुड़ी पाबंदियां

Android 7.0 (एपीआई लेवल 24) को टारगेट करने वाले ऐप्लिकेशन को CONNECTIVITY_ACTION ब्रॉडकास्ट नहीं मिलते, अगर वे उन्हें मेनिफ़ेस्ट में शामिल करने के लिए रजिस्टर करना होगा. साथ ही, ऐसी प्रोसेस जो इस पर निर्भर करती हैं ब्रॉडकास्ट शुरू नहीं होगा. इससे उन ऐप्लिकेशन के लिए समस्या हो सकती है जिन्हें नेटवर्क परिवर्तन को सुनने या बल्क नेटवर्क गतिविधियां करने के लिए जब आप डिवाइस किसी ऐसे नेटवर्क से कनेक्ट हो जाता है जिस पर डेटा इस्तेमाल की कोई सीमा न हो. इस समस्या से बचने के कई समाधान प्रतिबंध पहले से ही Android फ़्रेमवर्क में मौजूद है, लेकिन पहला, इस बात पर निर्भर करता है कि आपके ऐप्लिकेशन से कौनसा लक्ष्य हासिल करना है.

ध्यान दें: एक BroadcastReceiver, जिसके साथ रजिस्टर किया गया हो Context.registerReceiver() ऐप्लिकेशन के चलने के दौरान भी ये ब्रॉडकास्ट मिलते रहेंगे.

मीटर न किए गए कनेक्शन पर नेटवर्क जॉब शेड्यूल करें

JobInfo.Builder क्लास का इस्तेमाल करते समय अपना JobInfo ऑब्जेक्ट बनाने के लिए, 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);
}

जब आपकी नौकरी की शर्तें पूरी हो जाती हैं, तो आपके ऐप्लिकेशन को चलाने के लिए एक कॉलबैक मिलता है onStartJob() तरीका JobService.class बताया गया. JobScheduler को लागू करने के और उदाहरण देखने के लिए, नौकरी के शेड्यूल का सैंपल ऐप्लिकेशन देखें.

JobScheduler की जगह एक नया विकल्प है WorkManager, जो एक ऐसा एपीआई है जो आपको बैकग्राउंड में होने वाले ऐसे टास्क जिन्हें करने की ज़रूरत है ऐप्लिकेशन की प्रोसेस पूरी होने की गारंटी दी जाती है. इससे कोई फ़र्क़ नहीं पड़ता कि ऐप्लिकेशन को प्रोसेस किया जा रहा है या नहीं. वर्कमैनेजर काम को चलाने का सही तरीका चुनता है (या तो सीधे आपके ऐप्लिकेशन प्रोसेस में किसी थ्रेड पर के आधार पर दिखाया गया है. डिवाइस का एपीआई लेवल. इसके अलावा, WorkManager को Play services की ज़रूरत नहीं है. यह सिर्फ़ वह ऐप्लिकेशन उपलब्ध कराता है कई ऐडवांस सुविधाएं इस्तेमाल की जा सकती हैं. जैसे, टास्क को एक साथ जोड़ना या टास्क का स्टेटस देखना. सीखने में ज़्यादा जानने के लिए, WorkManager देखें.

ऐप्लिकेशन के चलने के दौरान, नेटवर्क कनेक्टिविटी पर नज़र रखें

चल रहे ऐप्लिकेशन, अब भी CONNECTIVITY_CHANGE की आवाज़ सुन सकते हैं. BroadcastReceiver को रजिस्टर किया गया. हालांकि, ConnectivityManager एपीआई, अनुरोध करने का ज़्यादा बेहतर तरीका उपलब्ध कराता है सिर्फ़ तब कॉलबैक करें, जब नेटवर्क की तय शर्तें पूरी हों.

NetworkRequest ऑब्जेक्ट NetworkCapabilities के हिसाब से नेटवर्क कॉलबैक. आपने लोगों तक पहुंचाया मुफ़्त में NetworkRequest.Builder क्लास के साथ NetworkRequest ऑब्जेक्ट बनाएं. registerNetworkCallback() अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है फिर NetworkRequest ऑब्जेक्ट को सिस्टम में पास करता है. टास्क कब शुरू होगा अगर नेटवर्क की शर्तें पूरी होती हैं, तो काम करने के लिए ऐप्लिकेशन को कॉलबैक मिलता है onAvailable() तरीका अपनी ConnectivityManager.NetworkCallback क्लास में बताया गया है.

ऐप्लिकेशन के बंद होने या कॉल करने तक, ऐप्लिकेशन को कॉलबैक मिलते रहेंगे unregisterNetworkCallback().

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

Android 7.0 (एपीआई लेवल 24) में, ऐप्लिकेशन ACTION_NEW_PICTURE या ACTION_NEW_VIDEO ब्रॉडकास्ट नहीं भेज सकते. इस पाबंदी से मदद मिलती है परफ़ॉर्मेंस और उपयोगकर्ता अनुभव पर पड़ने वाले असर को कम करना ज़रूरी है. ऐसा तब होता है, जब कई ऐप्लिकेशन के लिए नई इमेज या वीडियो प्रोसेस करने के लिए स्क्रीन चालू करें. Android 7.0 (एपीआई लेवल 24) कोई अन्य समस्या हल करने के लिए, JobInfo और JobParameters तक बढ़ाएं.

कॉन्टेंट यूआरआई में बदलावों पर जॉब ट्रिगर करें

कॉन्टेंट यूआरआई में बदलाव करने पर जॉब ट्रिगर करने के लिए, Android 7.0 (एपीआई लेवल 24) बढ़ाया जाता है JobInfo API का इस्तेमाल, इन तरीकों से किया जा सकता है:

JobInfo.TriggerContentUri()
अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है कॉन्टेंट यूआरआई में बदलावों पर जॉब ट्रिगर करने के लिए ज़रूरी पैरामीटर एनकैप्सुलेट करता है.
JobInfo.Builder.addTriggerContentUri()
अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है यह JobInfo को TriggerContentUri ऑब्जेक्ट देता है. 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 ऑब्जेक्ट होता है onStartJob() को भेजा गया MediaContentJob.class में तरीका.

पता लगाएं कि किस कॉन्टेंट अथॉरिटी ने किसी जॉब को ट्रिगर किया

Android 7.0 (एपीआई लेवल 24) JobParameters को इससे आपके ऐप्लिकेशन को, उस कॉन्टेंट के बारे में काम की जानकारी मिल सकेगी जिसके लिए कॉन्टेंट की अनुमति मिली है और यूआरआई ने जॉब को ट्रिगर किया:

Uri[] getTriggeredContentUris()
अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है यह फ़ंक्शन उन यूआरआई का कलेक्शन दिखाता है, जिन्होंने जॉब को ट्रिगर किया है. अगर किसी यूआरआई से जॉब ट्रिगर नहीं हुआ, तो यह null होगा (उदाहरण के लिए, जॉब किसी समयसीमा या अन्य वजह से ट्रिगर हुआ हो) या बदलावों की संख्या यूआरआई की वैल्यू 50 से ज़्यादा है.
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