الخدمات التي تعمل في المقدّمة

تؤدي الخدمات التي تعمل في المقدّمة عمليات يمكن للمستخدم ملاحظتها.

تعرض الخدمات التي تعمل في المقدّمة شريط حالة ، لإعلام المستخدمين بأنّ تطبيق ينفّذ مهمة في المقدّمة ويستهلك موارد النظام.

تشمل أمثلة التطبيقات التي تستخدم الخدمات التي تعمل في المقدّمة ما يلي:

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

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

يوضِّح هذا المستند الإذن المطلوب لاستخدام الخدمات التي تعمل في المقدّمة. وكيفية بدء خدمة تعمل في المقدّمة وإزالتها من الخلفية. وكذلك توضح كيفية ربط بعض حالات الاستخدام بأنواع الخدمات التي تعمل في المقدّمة قيود الوصول التي تسري عند بدء تشغيل خدمة تعمل في المقدّمة من تطبيق يعمل في الخلفية.

يمكن للمستخدم إغلاق الإشعار تلقائيًا

بدءًا من نظام التشغيل Android 13 (المستوى 33)، يمكن للمستخدمين إغلاق الإشعار. تكون مرتبطة بخدمة تعمل في المقدّمة بشكل تلقائي لإجراء ذلك، يُجري المستخدمون تمريرة سريعة إيماءة على الإشعار. في العادة، يتم إرسال الإشعار لا يتم إغلاقها ما لم يتم إيقاف الخدمة التي تعمل في المقدّمة أو إزالتها. من المقدمة.

إذا أردت أن لا يتمكن المستخدم من إغلاق الإشعار، يمكنك true إلى setOngoing() عند إنشاء الإشعار باستخدام Notification.Builder.

الخدمات التي تعرض إشعارًا على الفور

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

في نظام التشغيل Android 13 (المستوى 33 لواجهة برمجة التطبيقات) أو الإصدارات الأحدث، إذا رفض المستخدم إذن إرسال الإشعارات استمرار ظهور إشعارات ذات صلة بالخدمات التي تعمل في المقدّمة في إدارة المهام ولكن لا يمكن رؤيتها في درج الإشعارات.

يُرجى تعريف الخدمات التي تعمل في المقدّمة ضمن البيان.

في بيان تطبيقك، يجب ذكر كل خدمة من الخدمات التي تعمل في المقدّمة في تطبيقك. مع <service> العنصر. لكل خدمة، استخدم السمة android:foregroundServiceType للإعلان عن نوع العمل الذي تؤديه الخدمة.

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

<manifest xmlns:android="http://schemas.android.com/apk/res/android" ...>
  <application ...>

    <service
        android:name=".MyMediaPlaybackService"
        android:foregroundServiceType="mediaPlayback"
        android:exported="false">
    </service>
  </application>
</manifest>

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

android:foregroundServiceType="camera|microphone"

طلب أذونات الخدمات التي تعمل في المقدّمة

التطبيقات التي تستهدف الإصدار 9 من نظام التشغيل Android (المستوى 28 من واجهة برمجة التطبيقات) أو الإصدارات الأحدث وتستخدم خدمات تعمل في المقدّمة بحاجة إلى طلب FOREGROUND_SERVICE في بيان التطبيق، كما هو موضح في مقتطف الرمز التالي. وهذا أمر عادي إذن، وبالتالي سيعتمد النظام لمنحه تلقائيًا إلى التطبيق صاحب الطلب.

بالإضافة إلى ذلك، إذا كان التطبيق يستهدف المستوى 34 أو أعلى لواجهة برمجة التطبيقات، يجب أن يطلب نوع الإذن المناسب لنوع العمل الذي ستُجريه الخدمة التي تعمل في المقدّمة القيام به. كل نوع من أنواع الخدمات التي تعمل في المقدّمة لديه نوع إذن مطابق. على سبيل المثال، إذا بدأ أحد التطبيقات التي تعمل في المقدّمة تستخدم الكاميرا، يجب طلب كل من FOREGROUND_SERVICE وFOREGROUND_SERVICE_CAMERA الأذونات. هذه كلها أذونات عادية، لذا يمنحها النظام تلقائيًا إذا كانت مدرجة في البيان.

<manifest xmlns:android="http://schemas.android.com/apk/res/android" ...>

    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_CAMERA"/>

    <application ...>
        ...
    </application>
</manifest>

المتطلّبات الأساسية للخدمة التي تعمل في المقدّمة

بدءًا من نظام التشغيل Android 14 (المستوى 34)، عند تشغيل خدمة تعمل في المقدّمة، يتحقق النظام من متطلبات أساسية محددة بناءً على نوع الخدمة. على سبيل المثال: إذا حاولت تشغيل خدمة تعمل في المقدّمة من النوع location، سيتحقّق النظام من للتأكد من أنّ تطبيقك يحتوي حاليًا على ACCESS_COARSE_LOCATION أو إذن ACCESS_FINE_LOCATION. وإذا لم يحدث ذلك، يطرح النظام SecurityException

لهذا السبب، يجب التأكّد من استيفاء المتطلبات الأساسية المطلوبة. قبل بدء استخدام خدمة تعمل في المقدّمة. الخدمة التي تعمل في المقدّمة وثائق type المتطلبات الأساسية المطلوبة لكل نوع من أنواع الخدمات التي تعمل في المقدّمة.

بدء خدمة تعمل في المقدّمة

قبل أن تطلب من النظام تشغيل خدمة كخدمة تعمل في المقدّمة، ابدأ للخدمة نفسها:

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);

داخل الخدمة، والتي عادةً ما تكون في onStartCommand()، يمكنك طلب أنّ خدمتك في المقدّمة لإجراء ذلك، اتصل ServiceCompat.startForeground() (متوفّر في الإصدار 1.12 من androidx-core والإصدارات الأحدث). تتطلّب هذه الطريقة ما يلي: المَعلمات:

وقد تكون هذه الأنواع مجموعة فرعية من الأنواع التي تم تعريفها في البيان. اعتمادًا على حالة الاستخدام المحددة. بعد ذلك، إذا أردت إضافة المزيد من أنواع الخدمات يمكنك الاتصال بـ 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)
            }
            // ...
        }
    }

    //...
}

إزالة خدمة من المقدّمة

لإزالة الخدمة من المقدّمة، يُرجى الاتصال stopForeground() تستخدم هذه الطريقة قيمة منطقية تشير إلى ما إذا كان يجب إزالة شريط الحالة المستخدم العادي أيضًا. يُرجى ملاحظة أنّ الخدمة لا تزال تعمل.

في حال إيقاف الخدمة أثناء تشغيلها في المقدّمة، سيتم إرسال إشعارها. تمت إزالته.

معالجة الإيقاف الذي يبدأه المستخدم للتطبيقات التي تشغّل الخدمات التي تعمل في المقدّمة

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

بدءًا من Android 13 (المستوى 33)، يمكن للمستخدمين إكمال سير عمل من درج الإشعارات إيقاف تطبيق لديه خدمات جارية تعمل في المقدّمة، بغض النظر عن واجهة إصدار حزمة SDK المستهدف. هذه الوظيفة، التي تسمى مدير المهام، ويعرض قائمة بالتطبيقات يتم تشغيل خدمة تعمل في المقدّمة حاليًا.

تحمل هذه القائمة التصنيف التطبيقات النشطة. وبجانب كل تطبيق، يظهر زر إيقاف. يوضح الشكل 1 سير عمل "إدارة المهام" على جهاز يتم تشغيله Android 13.

عندما يضغط المستخدم على الزر إيقاف بجانب تطبيقك في "إدارة المهام"، ثم تحدث الإجراءات التالية:

  • يزيل النظام تطبيقك من الذاكرة. وبالتالي، يتوقّف تطبيقك بالكامل، وليس فقط مع الخدمة التي تعمل في المقدّمة.
  • يزيل النظام حزمة نشاط تطبيقك.
  • ويتوقّف تشغيل أي وسائط.
  • تتم إزالة الإشعار المرتبط بالخدمة التي تعمل في المقدّمة.
  • سيظل تطبيقك في السجلّ.
  • يتم تنفيذ المهام المُجدوَلة في الوقت المحدّد.
  • تنطلق المنبّهات في الوقت المحدَّد أو الإطار الزمني المحدَّد.

لاختبار سلوك تطبيقك على النحو المتوقّع أثناء وبعد أن يوقف المستخدم تشغيل التطبيق شغّل أمر ADB التالي في نافذة طرفية:

adb shell cmd activity stop-app PACKAGE_NAME

الإعفاءات

يوفّر النظام مستويات متعددة من الإعفاءات لأنواع معيّنة من التطبيقات، التي تصفها الأقسام التالية.

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

الإعفاءات من الظهور في "إدارة المهام" على الإطلاق

يمكن للتطبيقات التالية تشغيل خدمة تعمل في المقدّمة ولا تظهر في مدير المهام على الإطلاق:

  • التطبيقات على مستوى النظام
  • تطبيقات الأمان أي التطبيقات التي يتوفر لها الدور ROLE_EMERGENCY
  • الأجهزة الموجودة في الوضع التجريبي

إمكانية إيقاف عرض الإعفاءات من قِبل المستخدمين

عندما تشغِّل الأنواع التالية من التطبيقات خدمة تعمل في المقدّمة، تظهر في "مدير المهام"، ولكن لا يوجد زر إيقاف بجانب اسم التطبيق لينقر عليه المستخدم:

استخدام واجهات برمجة التطبيقات المخصصة لغرض محدّد بدلاً من الخدمات التي تعمل في المقدّمة

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

مستندات قوائم أنواع الخدمات التي تعمل في المقدّمة بدائل جيدة لاستخدامها بدلاً من الخدمات التي تعمل في المقدّمة.

قيود بدء الخدمة التي تعمل في المقدّمة من الخلفية

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

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

الإعفاءات من قيود البدء في الخلفية

في الحالات التالية، يمكن لتطبيقك بدء الخدمات التي تعمل في المقدّمة حتى أثناء يعمل تطبيقك في الخلفية:

القيود المفروضة على بدء الخدمات التي تعمل في المقدّمة التي تحتاج إلى أذونات أثناء الاستخدام

في نظام التشغيل Android 14 (المستوى 34 لواجهة برمجة التطبيقات) أو الإصدارات الأحدث، هناك مواقف خاصة يجب الانتباه إليها إذا كنت تبدأ خدمة تعمل في المقدّمة تحتاج إلى أذونات أثناء الاستخدام

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

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

وبالمثل، إذا كان تطبيقك في الخلفية وأنشأ خدمة صحية تحتاج إلى إذن BODY_SENSORS_BACKGROUND، تطبيق لا يمتلك هذا الإذن حاليًا، ويطرح النظام استثناءً. (لا ينطبق هذا إذا كانت خدمة صحية تحتاج إلى أذونات مختلفة، مثل ACTIVITY_RECOGNITION.) الاتصال PermissionChecker.checkSelfPermission() لا يمنع حدوث هذه المشكلة. إذا كان لدى تطبيقك إذن أثناء الاستخدام يستدعي الأداة checkSelfPermission() لمعرفة ما إذا كان حاصلاً على هذا الإذن، فإن الطريقة يعرض PERMISSION_GRANTED حتى إذا كان التطبيق يعمل في الخلفية. عندما تُرجع طريقة PERMISSION_GRANTED، فإنها تقول "حصل تطبيقك على هذا الإذن عندما يكون التطبيق قيد الاستخدام".

لهذا السبب، إذا كانت الخدمة التي تعمل في المقدّمة تحتاج إلى إذن أثناء الاستخدام، عليك يجب الاتصال بـ Context.startForegroundService() أو Context.bindService() أثناء يتضمّن تطبيقك نشاطًا مرئيًا، ما لم تندرج الخدمة في إحدى الاستثناءات المحدَّدة:

الإعفاءات من القيود المفروضة على الأذونات أثناء الاستخدام

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

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

تحتوي القائمة التالية على هذه الحالات:

  • يبدأ مكوّن النظام الخدمة.
  • تبدأ الخدمة بالتفاعل مع التطبيق التطبيقات المصغّرة.
  • تبدأ الخدمة بالتفاعل مع الإشعار.
  • تبدأ الخدمة PendingIntent الذي يتم إرساله من تطبيق مرئي آخر.
  • يبدأ تشغيل الخدمة من خلال تطبيق سياسة الجهاز. وحدة التحكّم التي تعمل في وضع مالك الجهاز.
  • تبدأ الخدمة بتطبيق يوفّر VoiceInteractionService.
  • تبدأ الخدمة عن طريق تطبيق يحتوي على إذن امتياز واحد (START_ACTIVITIES_FROM_BACKGROUND)
تحديد الخدمات المتأثرة في تطبيقك

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

Foreground service started from background can not have \
location/camera/microphone access: service SERVICE_NAME