قيود النظام على العمل في الخلفية

قد تستهلك العمليات في الخلفية استهلاكًا للذاكرة والبطارية. على سبيل المثال، قد يبدأ البث الضمني العديد من العمليات في الخلفية التي تم تسجيلها في واستمع إليه، حتى لو لم تؤدي هذه العمليات إلى الكثير من العمل. يمكن أن يكون لهذا تأثير كبير في أداء الجهاز وتجربة المستخدم.

لتجنّب قيود النظام، احرص على استخدام واجهة برمجة التطبيقات المناسبة مهمة خلفية. تشير رسالة الأشكال البيانية تساعدك مستندات نظرة عامة على المهام الخلفية في اختيار واجهة برمجة التطبيقات المناسبة لاحتياجاتك

القيود التي يبدأها المستخدم

في حال عرض أحد التطبيقات بعض السلوكيات السيئة الموضَّحة في مؤشرات Android الحيوية، يطلب النظام من المستخدم تقييد وصول هذا التطبيق إلى موارد النظام.

إذا لاحظ النظام أن أحد التطبيقات يستهلك موارد زائدة، فإنه يبلغ المستخدم، وتمنح المستخدم خيار تقييد إجراءات التطبيق. تشمل السلوكيات التي يمكن أن تؤدي إلى إرسال الإشعار ما يلي:

  1. عمليات قفل التنشيط المفرطة: قفل تنشيط جزئي واحد تم تعليقه لمدة ساعة عندما تكون الشاشة غير مفعّل
  2. الخدمات المفرطة في الخلفية: إذا كان التطبيق يستهدف مستويات أقل من 26 من واجهة برمجة التطبيقات ولديه خدمة زائدة عن الحد في الخلفية

تحدِّد الشركة المصنّعة للجهاز القيود الدقيقة التي تفرضها. بالنسبة على سبيل المثال، في إصدارات AOSP، لا يمكن للتطبيقات المحظورة تشغيل المهام أو تشغيل المنبّهات أو استخدام الشبكة، إلا عندما يكون التطبيق في المقدّمة.

القيود المفروضة على استقبال عمليات بث أنشطة الشبكة

لا تتلقّى التطبيقات إشعارات حول CONNECTIVITY_ACTION في حال التسجيل في وتلقيها في ملف البيان، والعمليات التي تعتمد على هذا البث لن تبدأ. وقد يمثل ذلك مشكلة بالنسبة إلى التطبيقات التي تريد الاستماع إلى بيانات الشبكة إجراء تغييرات أو تنفيذ أنشطة مجمّعة في الشبكة عند اتصال الجهاز شبكة غير محدودة. تتوفّر حاليًا العديد من الحلول للتغلّب على هذه القيود. ضمن إطار عمل Android، ولكن اختيار الإطار المناسب يعتمد على التي تريد أن يحققها تطبيقك.

جدولة العمل على الاتصالات التي لا تفرض تكلفة استخدام

عند إنشاء WorkRequest، أضِف NetworkType.UNMETERED Constraint.

fun scheduleWork(context: Context) {
    val workManager = WorkManager.getInstance(context)
    val workRequest = OneTimeWorkRequestBuilder<MyWorker>()
       .setConstraints(
           Constraints.Builder()
               .setRequiredNetworkType(NetworkType.UNMETERED)
               .build()
           )
       .build()

    workManager.enqueue(workRequest)
}

عند استيفاء شروط عملك، يتلقّى تطبيقك معاودة الاتصال لتشغيله. طريقة doWork() في فئة Worker المحددة.

مراقبة الاتصال بالشبكة أثناء تشغيل التطبيق

سيظل بإمكان التطبيقات قيد التشغيل الاستماع إلى محتوى "CONNECTIVITY_CHANGE" باستخدام تم التسجيل في BroadcastReceiver. في المقابل، تسمح واجهة برمجة التطبيقات ConnectivityManager توفر طريقة أكثر قوة لطلب معاودة الاتصال فقط عند تحديد شبكة استيفاء الشروط.

تحدِّد كائنات NetworkRequest مَعلمات معاودة الاتصال بالشبكة في البنود في NetworkCapabilities. تُنشئ NetworkRequest عناصر. مع الفئة NetworkRequest.Builder. registerNetworkCallback بعد ذلك، يتم تمرير الكائن NetworkRequest إلى النظام. عندما تعمل الشبكة استيفاء شروط معيّنة، يتلقّى التطبيق استدعاء لتنفيذ onAvailable() محددة في الصف ConnectivityManager.NetworkCallback.

يستمر التطبيق في تلقّي معاودة الاتصال إلى أن يتم الخروج من التطبيق أو عند الاتصال. unregisterNetworkCallback():

القيود المفروضة على تلقّي عمليات بث الصور والفيديوهات

لا يمكن للتطبيقات إرسال أو تلقّي ACTION_NEW_PICTURE أو ACTION_NEW_VIDEO من عمليات البث يساعد هذا القيد في تقليل ويؤثر في الأداء وتجربة المستخدم في الحالات التي يجب فيها تنشيط العديد من التطبيقات لمعالجة صورة جديدة أو فيديو جديد

تحديد مصادر المحتوى التي بدأت العمل

يسمح الإصدار WorkerParameters لتطبيقك بتلقّي معلومات مفيدة حول بدأت مراجع المحتوى ومعرّفات الموارد المنتظمة (URI) في العمل:

List<Uri> getTriggeredContentUris()

تعرض قائمة معرفات الموارد المنتظمة (URI) التي أدت إلى بدء العمل. يكون هذا الحقل فارغًا إذا لم يتم تشغيل أي معرّفات موارد منتظمة (URI) (على سبيل المثال، تم بدء العمل بسبب موعد نهائي أو أي سبب آخر) أو أن عدد معرفات الموارد المنتظمة (URI) الذي تم تغييره أكبر من 50-

List<String> getTriggeredContentAuthorities()

تعرض قائمة سلسلة من مراجع المحتوى التي شغَّلت العمل. في حال حذف القائمة المعروضة ليست فارغة، استخدم getTriggeredContentUris() لاسترداد تفاصيل معرفات الموارد المنتظمة (URI) التي تم تغييرها.

يلغي الرمز النموذجي التالي الطريقة CoroutineWorker.doWork() وتسجّل جهات المحتوى ومعرّفات الموارد المنتظمة (URI) التي أدّت إلى ظهور المهمة:

class MyWorker(
    appContext: Context,
    params: WorkerParameters
): CoroutineWorker(appContext, params)
    override suspend fun doWork(): Result {
        StringBuilder().apply {
            append("Media content has changed:\n")
            params.triggeredContentAuthorities
                .takeIf { it.isNotEmpty() }
                ?.let { authorities ->
                    append("Authorities: ${authorities.joinToString(", ")}\n")
                    append(params.triggeredContentUris.joinToString("\n"))
                } ?: append("(No content)")
            Log.i(TAG, toString())
        }
        return Result.success()
    }
}

اختبار التطبيق وفقًا لقيود النظام

عند تحسين تطبيقاتك لتعمل على أجهزة ذات ذاكرة منخفضة أو في ظروف تخزين قليلة الذاكرة، تحسين الأداء وتجربة المستخدم. إزالة التبعيات في الخلفية عبر خدمات وأجهزة استقبال البث الضمني المسجّلة في ملف البيان، تساعد تطبيقك تعمل بشكل أفضل على هذه الأجهزة. ننصح بتحسين تطبيقك لتشغيله دون استخدام هذه العمليات في الخلفية تمامًا.

يمكن أن تساعدك بعض أوامر Android Debug Bridge (ADB) الإضافية في اختبار التطبيق سلوكه عند إيقاف العمليات التي تتم في الخلفية:

  • لمحاكاة الظروف التي يتم فيها بث خدمات البث الضمنية والخدمات التي تعمل في الخلفية غير متاح، أدخل الأمر التالي:

    $ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND ignore

  • لإعادة تفعيل خدمات البث الضمنية والخدمات التي تعمل في الخلفية، أدخِل ما يلي: :

    $ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND allow

زيادة تحسين تطبيقك

للتعرّف على طرق جيدة أخرى لتحسين المهام التي تعمل في الخلفية سلوك، انظر تحسين استخدام البطارية لواجهات برمجة تطبيقات جدولة المهام التوثيق.