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

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

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

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

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

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

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

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

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

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

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

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

يجب أن تنتهي الخدمات التي تعمل في المقدّمة والتي تستخدم النوع short service بسرعة، أي في غضون ثلاث دقائق تقريبًا. عند انتهاء الوقت، يستدعي النظام طريقة 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() في غضون بضع ثوانٍ.

ForegroundServiceStartNotAllowedException

خطأ:

يعرض النظام الخطأ ForegroundServiceStartNotAllowedException.

السبب:

ويحدث ذلك عادةً عندما يبدأ التطبيق خدمة تعمل في المقدّمة من الخلفية بدون توفّر إذن إعفاء صالح.

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

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

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

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

الحلّ:

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

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

SecurityException

خطأ:

يطرح النظامSecurityException.

السبب:

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

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

الحلّ:

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