تتناول هذه الصفحة بعض الأسباب الشائعة التي قد تؤدي إلى تعذُّر تشغيل الخدمات التي تعمل في المقدّمة، وتساعدك في تحديد سبب المشكلة.
يتناول هذا المستند المشاكل التالية:
قبل تحديد المشاكل وحلّها
التحقّق من التغييرات الأخيرة على الخدمات التي تعمل في المقدّمة
إذا تم استخدام الخدمات التي تعمل في المقدّمة بشكل غير صحيح، يمكن أن تؤثر سلبًا في أداء الجهاز وعمر البطارية. لهذا السبب، غالبًا ما تُجري إصدارات نظام 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() في غضون بضع ثوانٍ.
WorkManager:
قد يظهر هذا الاستثناء أيضًا مع WorkManager المنفّذين الذين ينفّذون خدمة تعمل في المقدّمة (يتم استدعاء setForegound أو setForegroundAsync). عندما تتداخل مراحل نشاط منفّذَين يعملان في المقدّمة، حيث يحاول أحد المنفّذَين بدء خدمة تعمل في المقدّمة بينما تحاول خدمة أخرى تعمل في المقدّمة تم تشغيلها سابقًا إيقافها، سيصاحب هذا التعطّل السجلّ التالي:
Re-initializing SystemForegroundService after a request to shut-down
تم إصلاح هذا التعطُّل في الإصدار 2.10.5 من WorkManager.
إذا كان تطبيقك يواجه هذا الاستثناء، عليك تثبيت أحدث إصدار من WorkManager والإبلاغ عن أي مشاكل مستمرة في أداة تتبُّع المشاكل في WorkManager.
ForegroundServiceStartNotAllowedException
خطأ:
يعرض النظام ForegroundServiceStartNotAllowedException.
السبب:
ويحدث ذلك عادةً عندما يبدأ التطبيق خدمة تعمل في المقدّمة من الخلفية بدون وجود إذن إعفاء صالح.
بدءًا من Android 12 (المستوى 31 لواجهة برمجة التطبيقات)، لا يُسمح للتطبيقات ببدء الخدمات التي تعمل في المقدّمة أثناء تشغيل التطبيق في الخلفية، مع بعض الاستثناءات المحدّدة.
إذا حاولت بدء خدمة تعمل في المقدّمة من الخلفية ولم تستوفِ متطلبات أحد الاستثناءات، سيُظهر النظام الخطأ ForegroundServiceStartNotAllowedException. ويقوم النظام بذلك أيضًا في حال عدم استيفاء متطلبات الإعفاء.
على سبيل المثال، قد يتضمّن التطبيق زرًا يمكن للمستخدم النقر عليه، ما يؤدي إلى أن يجري التطبيق بعض المعالجة ثم يشغّل خدمة تعمل في المقدّمة. في هذه الحالة،
هناك خطر من أن ينقر المستخدم على الزر ثم يضع التطبيق في الخلفية على الفور. بعد ذلك، يحاول التطبيق تشغيل الخدمة
من الخلفية. إذا لم يستوفِ التطبيق أحد الاستثناءات المحدّدة، سيُصدر النظام ForegroundServiceStartNotAllowedException.
بالإضافة إلى ذلك، تتضمّن بعض الإعفاءات حدًا زمنيًا قصيرًا. على سبيل المثال، هناك إعفاء قصير المدة إذا كان تطبيقك يشغّل خدمة تعمل في المقدّمة استجابةً لرسالة ذات أولوية عالية من خدمة "مراسلة Firebase السحابية". إذا لم تشغّل الخدمة
بسرعة كافية، سيظهر لك الرمز ForegroundServiceStartNotAllowedException.
تصبح بعض الاستثناءات المحدّدة أكثر تقييدًا مع إصدارات Android الجديدة. إذا غيّرت إصدار Android الذي يستهدفه تطبيقك، راجِع مستندات التغييرات في الخدمات التي تعمل في المقدّمة وتأكَّد من أنّ تطبيقك لا يزال يستوفي أحد الاستثناءات المسموح بها.
الحلّ:
غيِّر سير عمل تطبيقك لكي لا يحتاج إلى تشغيل الخدمات التي تعمل في المقدّمة أثناء عمل التطبيق في الخلفية، أو أكِّد أنّ تطبيقك يستوفي أحد شروط الإعفاء.
يمكنك استخدام المكوّنات التي تراعي مراحل النشاط لإدارة مراحل نشاط تطبيقك حتى لا تحاول عن غير قصد تشغيل خدمة تعمل في المقدّمة من الخلفية.
SecurityException
خطأ:
يعرض النظامSecurityException.
السبب:
حاول تطبيقك تشغيل خدمة تعمل في المقدّمة بدون الحصول على الأذونات اللازمة.
- إذا كان التطبيق يستهدف الإصدار 9 من نظام التشغيل Android (المستوى 28 لواجهة برمجة التطبيقات) أو الإصدارات الأحدث، يجب أن يتضمّن الإذن
FOREGROUND_SERVICEلتشغيل خدمة تعمل في المقدّمة. - إذا كان التطبيق يستهدف الإصدار 14 من نظام التشغيل Android (المستوى 34 لواجهة برمجة التطبيقات) أو الإصدارات الأحدث، يجب أن يستوفي جميع المتطلبات الأساسية لنوع خدمة تعمل في المقدّمة. يتم توضيح هذه المتطلبات الأساسية بالتفصيل في مستندات أنواع الخدمات التي تعمل في المقدّمة. يُرجى الانتباه بشكل خاص إلى المتطلبات التالية:
- تتطلّب عدّة أنواع من الخدمات التي تعمل في المقدّمة أذونات تشغيل محدّدة. على سبيل المثال، يجب أن تتضمّن خدمة المراسلة عن بُعد التي تعمل في المقدّمة الإذن
FOREGROUND_SERVICE_REMOTE_MESSAGING.
- تتطلّب عدّة أنواع من الخدمات التي تعمل في المقدّمة أذونات تشغيل محدّدة. على سبيل المثال، يجب أن تتضمّن خدمة المراسلة عن بُعد التي تعمل في المقدّمة الإذن
- في عدة حالات، هناك قيود إضافية على الأذونات المطلوبة من بعض أنواع الخدمات التي تعمل في المقدّمة أثناء الاستخدام. ولا يتم منح هذه الأذونات للتطبيق إلا عندما يكون قيد الاستخدام (مع بعض
الاستثناءات المحددة). وهذا يعني أنّه حتى إذا طلب تطبيقك أحد هذه الأذونات وتم منحه إياه، سيُطلق النظام الخطأ
SecurityExceptionإذا حاول التطبيق تشغيل الخدمة التي تعمل في المقدّمة أثناء تشغيله في الخلفية، حتى إذا كان التطبيق معفيًا من شرط بدء تشغيل خدمة تعمل في المقدّمة من الخلفية. لمزيد من المعلومات، يُرجى الاطّلاع على قيود على بدء الخدمات التي تعمل في المقدّمة والتي تتطلّب أذونات "أثناء الاستخدام".- قد يظهر لك الخطأ
SecurityExceptionإذا طلبت الأذونات اللازمة ولكن بدأت الخدمة التي تعمل في المقدّمة قبل التأكّد من منح الأذونات المطلوبة.
- قد يظهر لك الخطأ
الحلّ:
قبل تشغيل الخدمة التي تعمل في المقدّمة، اطلب جميع أذونات الخدمة التي تعمل في المقدّمة المناسبة، وتأكَّد من استيفاء جميع المتطلبات الأساسية الأخرى لوقت التشغيل.