تحتاج التطبيقات غالبًا إلى تنفيذ أكثر من إجراء في كل مرة. توفر واجهات برمجة التطبيقات Android العديد من الطرق المختلفة للسماح لك بذلك. يعد اختيار الخيار الصحيح أمرًا مهمًا للغاية، فقد يكون الخيار مناسبًا لموقف ما ولكنه خاطئ جدًا في موقف آخر. يمكن أن يؤدي اختيار واجهات برمجة التطبيقات الخاطئة إلى الإضرار بأداء تطبيقك أو كفاءة الموارد، مما قد يستنزف طاقة البطارية ويضعف أداء جهاز المستخدم ككل. في بعض الحالات، قد يؤدي اختيار النهج الخاطئ إلى منع إدراج تطبيقك في متجر Play.
يشرح هذا المستند الخيارات المختلفة المتاحة لك ويساعدك على اختيار الخيار المناسب لموقفك.
المصطلحات
قد يتم استخدام بعض المصطلحات المهمة المتعلقة بمهام الخلفية بطرق متعددة ومتناقضة. ولهذا السبب، من المهم تحديد البنود الخاصة بنا.
إذا كان التطبيق قيد التشغيل في الخلفية، سيفرض النظام عددًا من القيود عليه. (على سبيل المثال، في معظم الحالات، لا يمكن لتطبيق موجود في الخلفية تشغيل الخدمات التي تعمل في المقدّمة.)
لأغراض هذا المستند، سنستخدم مصطلح "مهمة" للإشارة إلى عملية يقوم بها التطبيق خارج سير العمل الرئيسي. لضمان المواءمة في الفهم، وضعنا ذلك في ثلاث فئات رئيسية من أنواع المهام: العمل غير المتزامن وواجهات برمجة التطبيقات لجدولة المهام والخدمات التي تعمل في المقدّمة.
تحديد الخيار المناسب
في معظم السيناريوهات، يمكنك تحديد واجهات برمجة التطبيقات المناسبة لاستخدامها في مهمتك من خلال معرفة الفئة (عمل غير متزامن أو واجهات برمجة تطبيقات جدولة المهام أو الخدمات التي تعمل في المقدّمة) التي تندرج ضمنها المهمة.
إذا كنت لا تزال غير متأكد، يمكنك استخدام المخططات الانسيابية التي نقدمها والتي تضيف المزيد من التفاصيل الدقيقة إلى القرار. يتم وصف كل خيار من هذه الخيارات بمزيد من التفصيل لاحقًا في هذا المستند.
هناك سيناريوهان رئيسيان يجب مراعاتهما للمهام الأساسية:
- المهمة التي يبدأها المستخدم عندما يكون التطبيق مرئيًا
- يتم بدء المهمة استجابةً لحدث، سواء داخلي أم خارجي
لهذين السيناريوهين أشجار قرارات خاصة بهما.
العمل غير المتزامن
في كثير من الحالات، يحتاج التطبيق فقط إلى إجراء عمليات متزامنة أثناء تشغيله في المقدمة. على سبيل المثال، قد يحتاج التطبيق إلى إجراء عملية حسابية تستغرق وقتًا طويلاً. إذا أجرى العملية الحسابية على مؤشر ترابط واجهة المستخدم، فلن يكون المستخدم قادرًا على التفاعل مع التطبيق حتى انتهاء العملية الحسابية؛ وقد ينتج عن ذلك خطأ ANR. في مثل هذه الحالة، يجب أن يستخدم التطبيق خيار العمل غير المتزامن.
تتضمن خيارات العمل غير المتزامنة الشائعة عناصر كورروتينية في Kotlin وسلاسل محادثات Java. ويمكنك العثور على مزيد من المعلومات في وثائق العمل غير المتزامن. ومن المهم ملاحظة أنّه على عكس واجهات برمجة التطبيقات للمهام التي تعمل في الخلفية، لا يمكن ضمان انتهاء العمل غير المتزامن إذا لم يعد التطبيق في مرحلة دورة حياة صالحة (على سبيل المثال، إذا خرج التطبيق من المقدّمة).
واجهات برمجة التطبيقات لجدولة المهام
تمثِّل واجهات برمجة التطبيقات لجدولة المهام خيارًا أكثر مرونة عندما تحتاج إلى تنفيذ مهام
تحتاج إلى
مواصلة حتى بعد مغادرة المستخدم التطبيق. في معظم الحالات، يكون الخيار الأفضل
لتشغيل المهام التي تعمل في الخلفية هو استخدام WorkManager،
ولكن قد يكون من المناسب في بعض الحالات استخدام واجهة برمجة تطبيقات
JobScheduler
للنظام الأساسي.
WorkManager هي مكتبة قوية تتيح لك إعداد مهام بسيطة أو معقدة حسب حاجتك. يمكنك استخدام WorkManager لجدولة المهام لتشغيلها في أوقات محددة، أو تحديد الشروط التي يجب تشغيل المهمة فيها. يمكنك حتى إعداد سلاسل من المهام، بحيث تعمل كل مهمة بدورها، مع تمرير نتائجها إلى المهمة التالية. ولفهم جميع الخيارات المتاحة، يُرجى الاطّلاع على قائمة ميزات WorkManager.
تتضمن بعض السيناريوهات الأكثر شيوعًا للمهام التي يتم تنفيذها في الخلفية ما يلي:
- يتم جلب البيانات من الخادم بشكل دوري.
- استرجاع بيانات أداة الاستشعار (على سبيل المثال، بيانات عدّاد الخطوات)
- الحصول على بيانات الموقع الجغرافي بشكل دوري (يجب أن تحصل على إذن
ACCESS_BACKGROUND_LOCATION
على نظام التشغيل Android 10 أو الإصدارات الأحدث) - تحميل محتوى استنادًا إلى عامل تشغيل المحتوى، مثل الصور التي تم إنشاؤها بواسطة الكاميرا
الخدمات التي تعمل في المقدّمة
تقدّم الخدمات التي تعمل في المقدّمة طريقة فعّالة لتشغيل المهام التي تعمل في الحال بدون مقاطعة. ومع ذلك، من المحتمل أن تُحمّل الخدمات التي تعمل في المقدّمة عبئًا كبيرًا على الجهاز، وفي بعض الأحيان يكون لها آثار على الخصوصية والأمان. ولهذه الأسباب، يضع النظام الكثير من القيود على كيفية استخدام التطبيقات للخدمات التي تعمل في المقدّمة ومتى يمكن ذلك. على سبيل المثال، يجب أن تكون الخدمة التي تعمل في المقدّمة واضحة للمستخدم. وفي معظم الحالات، لا يمكن للتطبيقات تشغيل الخدمات التي تعمل في المقدّمة عندما تكون التطبيقات في الخلفية. لمزيد من المعلومات، راجع مستندات الخدمات التي تعمل في المقدّمة.
هناك طريقتان لإنشاء خدمة تعمل في المقدّمة. يمكنك الإفصاح عن
خدمة Service
الخاصة بك وتحديد أنّها
خدمة تعمل في المقدّمة من خلال طلب الرمز
Service.startForeground()
. بدلاً من ذلك، يمكنك استخدام WorkManager لإنشاء خدمة تعمل في المقدّمة، كما هو موضَّح في مقالة دعم العاملين لفترة طويلة.
من المهم معرفة أنّ أي خدمة تعمل في المقدّمة تم إنشاؤها بواسطة WorkManager يجب أن تتّبع جميع القيود نفسها المفروضة على أي خدمة أخرى تعمل في المقدّمة.
لا يوفّر WorkManager سوى بعض واجهات برمجة التطبيقات المناسبة لتسهيل إنشاء خدمة تعمل في المقدّمة.
واجهات برمجة التطبيقات البديلة
يوفّر النظام واجهات برمجة تطبيقات بديلة مُصمَّمة لتقديم أداء أفضل في حالات استخدام أكثر تحديدًا. في حال توفُّر واجهة برمجة تطبيقات بديلة لحالة الاستخدام، ننصحك باستخدام واجهة برمجة التطبيقات هذه بدلاً من الخدمة التي تعمل في المقدّمة، لأنّ ذلك من المفترض أن يساعد في تحسين أداء تطبيقك. تشير مستندات أنواع الخدمات التي تعمل في المقدّمة إلى الملاحظات حول الحالات التي تتوفّر فيها واجهة برمجة تطبيقات بديلة جيدة لاستخدامها بدلاً من نوع معيّن من الخدمات التي تعمل في المقدّمة.
في ما يلي بعض السيناريوهات الأكثر شيوعًا لاستخدام واجهات برمجة التطبيقات البديلة:
- استخدام عمليات نقل البيانات التي يبدأها المستخدم لإجراء عمليات تنزيل أو تحميل كبيرة، بدلاً من إنشاء خدمة تعمل في المقدّمة لمزامنة البيانات
- استخدام مدير الجهاز المصاحب للإقران عبر البلوتوث ونقل البيانات، بدلاً من استخدام خدمة تعمل في المقدّمة على جهاز متصل
- استخدام وضع "نافذة ضمن النافذة" لتشغيل الفيديو بدلاً من إنشاء خدمة تعمل في المقدّمة لتشغيل الوسائط
المهام التي بدأها المستخدم
إذا كان التطبيق بحاجة إلى أداء مهام في الخلفية، وكانت العملية هي التي يبدأها المستخدم عندما يكون التطبيق مرئيًا، أجب عن هذه الأسئلة للعثور على النهج الصحيح.
هل تحتاج إلى مواصلة تنفيذ المهمة أثناء تشغيل التطبيق في الخلفية؟
إذا لم تكن هناك حاجة لمواصلة تشغيل المهمة أثناء تشغيل التطبيق في الخلفية، يجب استخدام عمل غير متزامن. هناك عدد من الخيارات للقيام بالعمل غير المتزامن. من المهم أن نفهم أن هذه الخيارات تتوقف جميعها عن العمل إذا انتقل التطبيق إلى الخلفية. (وتتوقف أيضًا في حال إيقاف التطبيق). على سبيل المثال، قد يرغب أحد تطبيقات وسائل التواصل الاجتماعي في تحديث خلاصة المحتوى الخاصة به، لكن لن يحتاج إلى إنهاء العملية إذا غادر المستخدم الشاشة.
هل ستكون هناك تجربة مستخدم سيئة في حالة تأجيل المهمة أو مقاطعتها؟
من المهم مراعاة ما إذا كانت تجربة المستخدم ستتأثر إذا تم تأجيل مهمة ما أو إلغاؤها. على سبيل المثال، إذا كان التطبيق بحاجة إلى تحديث مواد العرض، قد لا يلاحظ المستخدم ما إذا كانت العملية تتم على الفور أم في منتصف الليل أثناء إعادة شحن الجهاز. في مثل هذه الحالات، يجب عليك استخدام خيارات العمل في الخلفية.
هل هي مهمة قصيرة وحاسمة؟
إذا تعذّر تأخير المهمة وسيتم إكمالها بسرعة، يمكنك استخدام خدمة تعمل في المقدّمة من النوع shortService
. إنّ إنشاء هذه
الخدمات أسهل من الخدمات الأخرى التي تعمل في المقدّمة، ولا تتطلّب عددًا كبيرًا من الأذونات. ومع ذلك، يجب أن تكتمل الخدمات القصيرة في غضون ثلاث دقائق.
هل توجد واجهة برمجة تطبيقات بديلة لهذا الغرض فقط؟
إذا لم تكن المهمة غير مرئية للمستخدم، قد يكون الحل الصحيح هو استخدام خدمة تعمل في المقدّمة. تعمل هذه الخدمات بشكل مستمر بمجرد بدؤها، لذلك فهي اختيار جيد عندما يؤدي مقاطعة المهمة إلى تجربة مستخدم سيئة. على سبيل المثال، قد يستخدم تطبيق تتبع التمرين أدوات استشعار الموقع للسماح للمستخدمين بتسجيل مسار الركض على الخريطة. لن ترغب في القيام بذلك باستخدام خيار عمل في الخلفية، لأنه إذا تم إيقاف المهمة مؤقتًا، سيتوقف التتبع على الفور. في مثل هذه الحالة، تكون الخدمة التي تعمل في المقدّمة هي الأكثر منطقية.
ومع ذلك، بما أنّ الخدمات التي تعمل في المقدّمة يمكن أن تستخدم الكثير من موارد الجهاز، يضع النظام الكثير من القيود على وقت وطريقة استخدامها. في كثير من الحالات، بدلاً من استخدام خدمة تعمل في المقدّمة، يمكنك استخدام واجهة برمجة تطبيقات بديلة تتولى المهمة المطلوبة نيابةً عنك. على سبيل المثال، إذا كان تطبيقك يحتاج إلى اتخاذ إجراء عند وصول المستخدم إلى موقع جغرافي معيّن، يكون الخيار الأفضل بالنسبة إليك هو استخدام واجهة برمجة تطبيقات الموقع الجغرافي بدلاً من تتبُّع الموقع الجغرافي للمستخدم من خلال خدمة تعمل في المقدّمة.
المهام ردًا على حدث
في بعض الأحيان، يحتاج أحد التطبيقات إلى تنفيذ عمل في الخلفية استجابةً للعامل، مثل:
- رسائل البث
- رسائل "المراسلة عبر السحابة الإلكترونية من Firebase" (FCM)
- المنبهات التي يضبطها التطبيق
قد يكون هذا مشغّلاً خارجيًا (مثل رسالة "المراسلة عبر السحابة الإلكترونية من Firebase") أو قد يكون استجابة لمنبّه يضبطه التطبيق نفسه. على سبيل المثال، قد تتلقى اللعبة رسالة من "المراسلة عبر السحابة الإلكترونية من Firebase" تطلب منها تعديل بعض مواد العرض.
إذا كنت متأكدًا من اكتمال المهمة في غضون بضع ثوانٍ، فاستخدم العمل غير المتزامن لتنفيذ المهمة. سيسمح النظام لتطبيقك بضع ثوانٍ لتنفيذ أي من هذه المهام، حتى لو كان تطبيقك يعمل في الخلفية.
إذا استغرقت المهمة أكثر من بضع ثوانٍ، قد يكون من المناسب بدء خدمة تعمل في المقدّمة لمعالجة المهمة. في الواقع، حتى إذا كان تطبيقك يعمل حاليًا في الخلفية، قد يُسمح له ببدء خدمة تعمل في المقدّمة إذا شغّلها المستخدم وكانت إحدى حالات الاستثناء من قيود بدء تشغيل الخلفية التي تمت الموافقة عليها. على سبيل المثال، إذا تلقّى التطبيق رسالة ذات أولوية عالية من خدمة "المراسلة عبر السحابة الإلكترونية من Firebase"، يُسمح للتطبيق ببدء خدمة تعمل في المقدّمة حتى إذا كان التطبيق يعمل في الخلفية.
إذا كانت المهمة ستستغرق أكثر من بضع ثوانٍ، استخدِم واجهات برمجة التطبيقات الخاصة بجدولة المهام.