تتناول هذه الصفحة بعض الأسباب الشائعة لتعطُّل الخدمات التي تعمل في المقدّمة وتساعدك في تحديد سبب المشكلة.
يتناول هذا المستند المشاكل التالية:
قبل تحديد المشاكل وحلّها
التحقّق من التغييرات الأخيرة في الخدمات التي تعمل في المقدّمة
إذا تم استخدام الخدمات التي تعمل في المقدّمة بشكل غير صحيح، يمكن أن يكون لها تأثيرات سلبية على أداء الجهاز وعمر البطارية. لهذا السبب، غالبًا ما تُجري إصدارات نظام 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.
ForegroundServiceStartNotAllowedException
الخطأ:
يعرض النظام الخطأ ForegroundServiceStartNotAllowedException.
السبب:
يحدث هذا عادةً بسبب تشغيل التطبيق لخدمة تعمل في المقدّمة من الخلفية في حال عدم توفّر استثناء صالح.
بدءًا من الإصدار 12 من نظام التشغيل Android (المستوى 31 لواجهة برمجة التطبيقات)، لا يُسمح للتطبيقات ببدء الخدمات التي تعمل في المقدّمة أثناء تشغيل التطبيق في الخلفية، مع بعض الاستثناءات المحدّدة.
إذا حاولت بدء خدمة تعمل في المقدّمة من الخلفية ولم تستوفِ متطلبات أحد الاستثناءات، سيعرض النظام الخطأ ForegroundServiceStartNotAllowedException. ويفعل النظام ذلك أيضًا إذا لم تستوفِ متطلبات الإعفاء.
على سبيل المثال، قد يحتوي التطبيق على زر يمكن للمستخدم النقر عليه، ما يؤدي إلى
إجراء التطبيق لبعض عمليات المعالجة ثم تشغيل خدمة تعمل في المقدّمة. في هذه الحالة،
هناك خطر من أن ينقر المستخدم على الزر ثم يضع
التطبيق على الفور في الخلفية. بعد ذلك، سيحاول التطبيق تشغيل الخدمة
من الخلفية. إذا لم يستوفِ التطبيق أحد الاستثناءات المحدّدة،
سيظهر الخطأ ForegroundServiceStartNotAllowedException.
بالإضافة إلى ذلك، تكون بعض الإعفاءات محدودة المدة. على سبيل المثال، هناك إعفاء لفترة وجيزة إذا كان تطبيقك يشغّل خدمة تعمل في المقدّمة استجابةً لرسالة FCM ذات أولوية عالية. إذا لم تطلق الخدمة
بسرعة كافية، فستحصل على ForegroundServiceStartNotAllowedException.
قد تصبح بعض الاستثناءات المحدّدة أكثر تقييدًا في بعض الأحيان مع إصدارات Android الجديدة. إذا غيّرت إصدار Android الذي يستهدفه تطبيقك، يُرجى مراجعة مستندات التغييرات في الخدمات التي تعمل في المقدّمة والتأكّد من أنّ تطبيقك لا يزال يستوفي أحد الاستثناءات المسموح بها.
الحلّ:
يُرجى تغيير سير عمل تطبيقك كي لا يحتاج إلى تشغيل الخدمات التي تعمل في المقدّمة أثناء تشغيل التطبيق في الخلفية، أو التأكّد من أنّ تطبيقك يستوفي أحد شروط الإعفاء.
يمكنك استخدام المكوّنات التي تراعي مراحل النشاط لإدارة مراحل نشاط تطبيقك حتى لا تحاول عن غير قصد تشغيل خدمة تعمل في المقدّمة من الخلفية.
SecurityException
الخطأ:
يعرض النظام الخطأ SecurityException.
السبب:
حاول تطبيقك تشغيل خدمة تعمل في المقدّمة بدون الحصول على الأذونات اللازمة.
- إذا كان التطبيق يستهدف الإصدار 9 من نظام التشغيل Android (مستوى واجهة برمجة التطبيقات 28) أو الإصدارات الأحدث، يجب أن يحصل على إذن
FOREGROUND_SERVICEلتشغيل خدمة تعمل في المقدّمة. - إذا كان التطبيق يستهدف الإصدار 14 من نظام التشغيل Android (المستوى 34 لواجهة برمجة التطبيقات) أو الإصدارات الأحدث، يجب أن يستوفي جميع المتطلبات الأساسية لنوع الخدمة التي تعمل في المقدّمة. هذه المتطلبات الأساسية موضّحة بالتفصيل في مستندات أنواع الخدمات التي تعمل في المقدّمة. يُرجى الانتباه إلى المتطلبات التالية على وجه الخصوص:
- تتطلّب عدة أنواع من الخدمات التي تعمل في المقدّمة أذونات تشغيل محدّدة. على سبيل المثال، يجب أن تحصل خدمة المراسلة عن بُعد التي تعمل في المقدّمة على إذن
FOREGROUND_SERVICE_REMOTE_MESSAGING.
- تتطلّب عدة أنواع من الخدمات التي تعمل في المقدّمة أذونات تشغيل محدّدة. على سبيل المثال، يجب أن تحصل خدمة المراسلة عن بُعد التي تعمل في المقدّمة على إذن
- في عدة حالات، هناك قيود إضافية على الأذونات التي تحتاجها بعض أنواع الخدمات التي تعمل في المقدّمة أثناء الاستخدام. لا يتم منح هذه الأذونات للتطبيق إلا عندما يكون قيد الاستخدام (مع بعض الاستثناءات المحدّدة). وهذا يعني أنّه حتى إذا طلب تطبيقك أحد هذه الأذونات وتم منحه إياها، فسيُظهر النظام
SecurityExceptionإذا حاول التطبيق تشغيل الخدمة التي تعمل في المقدّمة أثناء تشغيله في الخلفية، حتى إذا كان التطبيق معفيًا من بدء خدمة تعمل في المقدّمة من الخلفية. لمزيد من المعلومات، يُرجى الاطّلاع على القيود المفروضة على تشغيل الخدمات التي تعمل في المقدّمة والتي تتطلّب أذونات أثناء الاستخدام.- قد يظهر لك الخطأ
SecurityExceptionإذا طلبت الأذونات اللازمة ولكنك بدأت الخدمة التي تعمل في المقدّمة قبل التأكّد من منح الأذونات المطلوبة.
- قد يظهر لك الخطأ
الحلّ:
قبل تشغيل الخدمة التي تعمل في المقدّمة، اطلب جميع الأذونات المناسبة لهذه الخدمة، وتأكَّد من استيفاء جميع المتطلبات الأساسية الأخرى لوقت التشغيل.