تحديد المشاكل وحلّها في الخدمات التي تعمل في المقدّمة

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

يناقش هذا المستند المشاكل التالية:

قبل تحديد المشاكل وحلّها

التحقّق من التغييرات الأخيرة على الخدمات التي تعمل في المقدّمة

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

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

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

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

أخطاء "التطبيق لا يستجيب" (ANR)

في ظروف معيّنة، من المفترض أن يوقف التطبيق خدمته التي تعمل في المقدّمة. إذا لم يوقف التطبيق الخدمة، يوقف النظام الخدمة ويؤدي إلى حدوث خطأ التطبيق لا يستجيب (ANR).

تشغيل خدمة قصيرة لمدة طويلة جدًا، ما يؤدي إلى حدوث خطأ ANR

يجب أن تكتمل الخدمات التي تعمل في المقدّمة والتي تستخدم نوع الخدمة القصيرة بسرعة، في غضون ثلاث دقائق تقريبًا. عند انتهاء الوقت، يستدعي النظام طريقة الخدمة Service.onTimeout(int,int). أمام الخدمة بضع ثوانٍ لاستدعاء stopSelf(). إذا لم توقف الخدمة نفسها، يؤدي النظام إلى حدوث خطأ "التطبيق لا يستجيب".

التشخيص:

إذا كان خطأ ANR ناتجًا عن عدم تمكُّن خدمة تعمل في المقدّمة من إيقاف نفسها، يعرض النظام استثناءً داخليًا. يمكنك التأكّد من أنّ هذه هي المشكلة من خلال مراجعة تقارير أخطاء ANR. إذا كانت هذه هي المشكلة، سيتضمّن التقرير الرسالة التالية:

Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type FOREGROUND_SERVICE_TYPE_SHORT_SERVICE did not stop within its timeout:
[component name]"

الحلّ:

تأكَّد من أنّ جميع الخدمات التي تعمل في المقدّمة والمحدودة بوقت تُنهي عملها وتستدعي stopForeground(int) ضمن الحدّ الزمني للنظام.

اطلب من خدماتك التي تعمل في المقدّمة تنفيذ Service.onTimeout(int,int). تأكَّد من أنّ تنفيذك لهذه الطريقة يستدعي stopSelf() على الفور.

استثناءات الخدمات التي تعمل في المقدّمة

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

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

استثناء داخلي: تم تجاوز المهلة

يفرض النظام حدًا زمنيًا على مدة تشغيل الخدمات التي تعمل في المقدّمة لمزامنة البيانات ومعالجة الوسائط أثناء تشغيل التطبيق في الخلفية. إذا تجاوزت الخدمة هذا الحدّ، يستدعي النظام طريقة Service.onTimeout(int,int) للخدمة. أمام الخدمة بضع ثوانٍ لاستدعاء stopSelf(). إذا لم توقف الخدمة نفسها، ينشئ النظام RemoteServiceException داخليًا يؤدي إلى تعطُّل التطبيق.

التشخيص:

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

Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type [service type] did not stop within its timeout: [component name]"

الحلّ:

تأكَّد من أنّ جميع الخدمات التي تعمل في المقدّمة والمحدودة بوقت تُنهي عملها وتستدعي stopForeground(int) ضمن الحدّ الزمني للنظام.

اطلب من خدماتك التي تعمل في المقدّمة تنفيذ Service.onTimeout(int,int). تأكَّد من أنّ تنفيذك لهذه الطريقة يستدعي stopSelf() على الفور.

استثناء داخلي: ForegroundServiceDidNotStartInTimeException

عند تشغيل خدمة من خلال استدعاء context.startForegroundService()، أمام هذه الخدمة بضع ثوانٍ لترقيتها إلى خدمة تعمل في المقدّمة من خلال استدعاء ServiceCompat.startForeground(). إذا لم تفعل الخدمة ذلك، يعرض النظام ForegroundServiceDidNotStartInTimeException داخليًا.

التشخيص:

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

android.app.RemoteServiceException$ForegroundServiceDidNotStartInTimeException:
Context.startForegroundService() did not then call Service.startForeground()

الحلّ:

تأكَّد من أنّ جميع الخدمات التي تعمل في المقدّمة والتي تم إنشاؤها حديثًا تستدعي ServiceCompat.startForeground() في غضون بضع ثوانٍ.

WorkManager:

قد يظهر لك هذا الاستثناء أيضًا مع عناصر WorkManager التي تنّفذ خدمة تعمل في المقدّمة (تستدعي setForegound أو setForegroundAsync). عندما تتداخل دورة حياة عنصرَي عمل يعملان في المقدّمة، حيث يحاول أحد العنصرَين بدء خدمة تعمل في المقدّمة بينما يحاول عنصر عمل آخر كان قيد التشغيل في المقدّمة إيقاف نفسه، سيصاحب هذا التعطُّل السجلّ التالي:

Re-initializing SystemForegroundService after a request to shut-down

تم تقديم حلّ لهذا التعطُّل في الإصدار 2.10.5 من WorkManager.

إذا كان تطبيقك يواجه هذا الاستثناء، عليك التعديل إلى أحدث إصدار من WorkManager والإبلاغ عن أي مشاكل مستمرة في أداة تتبُّع مشاكل WorkManager issue tracker.

ForegroundServiceStartNotAllowedException

الخطأ:

يعرض النظام ForegroundServiceStartNotAllowedException.

السبب:

ينتج هذا عادةً عن تشغيل التطبيق خدمة تعمل في المقدّمة من الخلفية بدون وجود إعفاء صالح.

اعتبارًا من Android 12 (المستوى 31 من واجهة برمجة التطبيقات)، لا يُسمح للتطبيقات ببدء خدمات تعمل في المقدّمة أثناء تشغيل التطبيق في الخلفية، مع بعض الإعفاءات المحدّدة. إذا حاولت تشغيل خدمة تعمل في المقدّمة من الخلفية ولم تستوفِ متطلبات أحد الإعفاءات، يعرض النظام ForegroundServiceStartNotAllowedException. يفعل النظام ذلك أيضًا إذا لم تستوفِ متطلبات الإعفاء.

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

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

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

الحلّ:

غيِّر سير عمل تطبيقك بحيث لا يحتاج إلى تشغيل خدمات تعمل في المقدّمة أثناء تشغيل التطبيق في الخلفية، أو تأكَّد من أنّ تطبيقك يستوفي أحد الإعفاءات.

يمكنك استخدام المكوّنات التي تراعي مراحل النشاط لإدارة مراحل نشاط تطبيقك حتى لا تحاول عن قصد تشغيل خدمة تعمل في المقدّمة من الخلفية.

‎SecurityException

الخطأ:

يعرض النظام SecurityException.

السبب:

حاول تطبيقك تشغيل خدمة تعمل في المقدّمة بدون الحصول على الأذونات اللازمة.

  • إذا كان التطبيق يستهدف Android 9 (المستوى 28 من واجهة برمجة التطبيقات) أو الإصدارات الأحدث، يجب أن يكون لديه إذن FOREGROUND_SERVICE لتشغيل خدمة تعمل في المقدّمة.
  • إذا كان التطبيق يستهدف Android 14 (المستوى 34 من واجهة برمجة التطبيقات) أو الإصدارات الأحدث، يجب أن يستوفي جميع المتطلبات الأساسية لنوع الخدمة التي تعمل في المقدّمة. تم توضيح هذه المتطلبات الأساسية بالتفصيل في مستندات أنواع الخدمات التي تعمل في المقدّمة. على وجه الخصوص، يُرجى الانتباه إلى المتطلبات التالية:
    • تتطلب عدة أنواع من الخدمات التي تعمل في المقدّمة أذونات معيّنة في وقت التشغيل. على سبيل المثال، يجب أن يكون لدى خدمة المراسلة عن بُعد التي تعمل في المقدّمة إذن FOREGROUND_SERVICE_REMOTE_MESSAGING.
  • في عدة حالات، هناك قيود إضافية أثناء الاستخدام على الأذونات التي تحتاجها بعض أنواع الخدمات التي تعمل في المقدّمة. لا يتم منح هذه الأذونات للتطبيق إلا أثناء تشغيله في المقدّمة (مع بعض الاستثناءات المحدّدة). يعني ذلك أنّه حتى إذا طلب تطبيقك أحد هذه الأذونات وتم منحه إياها، إذا حاول التطبيق تشغيل الخدمة التي تعمل في المقدّمة أثناء تشغيله في الخلفية، سيعرض النظام SecurityException حتى إذا كان التطبيق لديه إعفاء لبدء خدمة تعمل في المقدّمة من الخلفية. لمزيد من المعلومات، يُرجى الاطّلاع على قيود على بدء الخدمات التي تعمل في المقدّمة والتي تحتاج إلى أذونات أثناء الاستخدام الاستخدام.
    • قد يظهر لك SecurityException إذا طلبت الأذونات اللازمة ولكنك بدأت الخدمة التي تعمل في المقدّمة قبل التأكّد من منح الأذونات المطلوبة.

الحلّ:

قبل تشغيل الخدمة التي تعمل في المقدّمة، اطلب جميع أذونات الخدمة التي تعمل في المقدّمة المناسبة، وتأكَّد من أنّك استوفيت جميع المتطلبات الأساسية الأخرى في وقت التشغيل.