هناك خطوتان لبدء خدمة تعمل في المقدّمة من تطبيقك. أولاً، عليك بدء الخدمة من خلال استدعاء context.startForegroundService()
. بعد ذلك، اطلب من الخدمة استدعاء ServiceCompat.startForeground()
لترقيتها إلى خدمة تعمل في المقدّمة.
المتطلّبات الأساسية
اعتمادًا على مستوى واجهة برمجة التطبيقات الذي يستهدفه تطبيقك، هناك بعض القيود على الحالات التي يمكن فيها للتطبيق تشغيل خدمة تعمل في المقدّمة.
لا يُسمح للتطبيقات التي تستهدف الإصدار 12 من نظام التشغيل Android (المستوى 31 لواجهة برمجة التطبيقات) أو الإصدارات الأحدث ببدء خدمة تعمل في المقدّمة أثناء عمل التطبيق في الخلفية، مع بعض الاستثناءات المحدّدة. لمزيد من المعلومات حول هذا الإجراء والاستثناءات من هذه القاعدة، يُرجى الاطّلاع على قيود على بدء خدمة تعمل في المقدّمة من الخلفية.
يجب أن تطلب التطبيقات التي تستهدف الإصدار 14 من نظام التشغيل Android (المستوى 34 لواجهة برمجة التطبيقات) أو الإصدارات الأحدث الأذونات المناسبة لنوع الخدمة التي تعمل في المقدّمة. عندما يحاول التطبيق ترقية خدمة إلى المقدّمة، يتحقّق النظام من الأذونات المناسبة ويعرض الخطأ
SecurityException
إذا كان التطبيق يفتقد أيًا منها. على سبيل المثال، إذا حاولت تشغيل خدمة تعمل في المقدّمة من النوعlocation
، يتحقّق النظام للتأكّد من أنّ تطبيقك لديه الإذنACCESS_COARSE_LOCATION
أوACCESS_FINE_LOCATION
. تتضمّن مستندات نوع الخدمة التي تعمل في المقدّمة المتطلبات الأساسية اللازمة لكل نوع من أنواع الخدمات التي تعمل في المقدّمة.
إطلاق خدمة
لبدء خدمة تعمل في المقدّمة، يجب أولاً بدء تشغيلها كخدمة عادية (غير خدمة تعمل في المقدّمة):
Kotlin
val intent = Intent(...) // Build the intent for the service context.startForegroundService(intent)
Java
Context context = getApplicationContext(); Intent intent = new Intent(...); // Build the intent for the service context.startForegroundService(intent);
النقاط الرئيسية حول الرمز
- يُطلق مقتطف الرمز خدمة. ومع ذلك، لم يتم تشغيل الخدمة في المقدّمة بعد. داخل الخدمة نفسها، عليك استدعاء
ServiceCompat.startForeground()
لترقية الخدمة إلى خدمة تعمل في المقدّمة.
نقل خدمة إلى المقدّمة
بعد تشغيل إحدى الخدمات، عليك استدعاء ServiceCompat.startForeground()
لطلب تشغيل الخدمة في المقدّمة. عادةً ما يتم استدعاء هذه الطريقة في طريقة onStartCommand()
الخاصة بالخدمة.
تتضمّن ServiceCompat.startForeground()
المَعلمات التالية:
- الخدمة
- عدد صحيح موجب يحدّد بشكل فريد إشعار الخدمة في شريط الحالة.
- كائن
Notification
نفسه - نوع أو أنواع الخدمة التي تعمل في المقدّمة التي تحدّد العمل الذي تؤدّيه الخدمة
أنواع الخدمات التي تعمل في المقدّمة والتي يتم تمريرها إلى startForeground()
الأنواع المحدّدة في البيان، وذلك حسب حالة الاستخدام المحدّدة. بعد ذلك، إذا كنت بحاجة إلى إضافة المزيد من أنواع الخدمات، يمكنك الاتصال على startForeground()
مرة أخرى.
على سبيل المثال، لنفترض أنّ تطبيق لياقة بدنية يشغّل خدمة لتتبُّع الجري تحتاج دائمًا إلى معلومات location
، ولكنها قد تحتاج أو لا تحتاج إلى تشغيل الوسائط. عليك تعريف كل من location
وmediaPlayback
في ملف البيان. إذا بدأ المستخدم نشاطًا رياضيًا وأراد تتبُّع موقعه الجغرافي فقط، يجب أن يستدعي تطبيقك startForeground()
وأن يمرِّر إذن ACCESS_FINE_LOCATION
فقط. بعد ذلك، إذا أراد المستخدم بدء تشغيل الصوت، عليه استدعاء startForeground()
مرة أخرى وتمرير المجموعة الثنائية لجميع أنواع الخدمات التي تعمل في المقدّمة (في هذه الحالة، ACCESS_FINE_LOCATION|FOREGROUND_SERVICE_MEDIA_PLAYBACK
).
يوضّح المثال التالي الرمز البرمجي الذي تستخدمه خدمة الكاميرا لترقية نفسها إلى خدمة تعمل في المقدّمة:
Kotlin
class MyCameraService: Service() { private fun startForeground() { // Before starting the service as foreground check that the app has the // appropriate runtime permissions. In this case, verify that the user has // granted the CAMERA permission. val cameraPermission = PermissionChecker.checkSelfPermission(this, Manifest.permission.CAMERA) if (cameraPermission != PermissionChecker.PERMISSION_GRANTED) { // Without camera permissions the service cannot run in the foreground // Consider informing user or updating your app UI if visible. stopSelf() return } try { val notification = NotificationCompat.Builder(this, "CHANNEL_ID") // Create the notification to display while the service is running .build() ServiceCompat.startForeground( /* service = */ this, /* id = */ 100, // Cannot be 0 /* notification = */ notification, /* foregroundServiceType = */ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA } else { 0 }, ) } catch (e: Exception) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && e is ForegroundServiceStartNotAllowedException) { // App not in a valid state to start foreground service // (e.g. started from bg) } // ... } } }
Java
public class MyCameraService extends Service { private void startForeground() { // Before starting the service as foreground check that the app has the // appropriate runtime permissions. In this case, verify that the user // has granted the CAMERA permission. int cameraPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA); if (cameraPermission == PackageManager.PERMISSION_DENIED) { // Without camera permissions the service cannot run in the // foreground. Consider informing user or updating your app UI if // visible. stopSelf(); return; } try { Notification notification = new NotificationCompat.Builder(this, "CHANNEL_ID") // Create the notification to display while the service // is running .build(); int type = 0; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { type = ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA; } ServiceCompat.startForeground( /* service = */ this, /* id = */ 100, // Cannot be 0 /* notification = */ notification, /* foregroundServiceType = */ type ); } catch (Exception e) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && e instanceof ForegroundServiceStartNotAllowedException ) { // App not in a valid state to start foreground service // (e.g started from bg) } // ... } } //... }
النقاط الرئيسية حول الرمز
- وقد سبق أن أعلن التطبيق في البيان عن حاجته إلى إذن
CAMERA
. ومع ذلك، يجب أن يتحقّق التطبيق أيضًا أثناء التشغيل للتأكّد من أنّ المستخدم منح هذا الإذن. إذا لم يكن لدى التطبيق الأذونات الصحيحة، يجب أن يُعلم المستخدم بالمشكلة. - تم طرح أنواع مختلفة من الخدمات التي تعمل في المقدّمة مع إصدارات مختلفة من منصة Android. يتحقّق هذا الرمز من إصدار Android الذي يتم تشغيله ويطلب الأذونات المناسبة.
- يتحقّق الرمز من
ForegroundServiceStartNotAllowedException
في حال كان يحاول بدء خدمة تعمل في المقدّمة في موقف غير مسموح به (على سبيل المثال، إذا كان يحاول الترويج للخدمة في المقدّمة بينما يكون التطبيق قيد التشغيل في الخلفية).