راه اندازی سرویس پیش زمینه، راه اندازی سرویس پیش زمینه، راه اندازی سرویس پیش زمینه

دو مرحله برای راه اندازی یک سرویس پیش زمینه از برنامه شما وجود دارد. ابتدا باید سرویس را با فراخوانی context.startForegroundService() شروع کنید. سپس، از سرویس بخواهید که ServiceCompat.startForeground() فراخوانی کند تا خود را به یک سرویس پیش زمینه معرفی کند.

پیش نیازها

بسته به اینکه برنامه شما کدام سطح API را هدف قرار می‌دهد، محدودیت‌هایی در زمانی که یک برنامه بتواند سرویس پیش‌زمینه راه‌اندازی کند، وجود دارد.

  • برنامه‌هایی که Android 12 (سطح API 31) یا بالاتر را هدف قرار می‌دهند، اجازه ندارند سرویس پیش‌زمینه را در حالی که برنامه در پس‌زمینه است راه‌اندازی کنند، به استثنای چند استثنا. برای اطلاعات بیشتر و اطلاعات در مورد استثناهای این قانون، به محدودیت‌های شروع سرویس پیش‌زمینه از پس‌زمینه مراجعه کنید.

  • برنامه‌هایی که Android 14 (سطح API 34) یا بالاتر را هدف قرار می‌دهند باید مجوزهای مناسب را برای نوع سرویس پیش‌زمینه درخواست کنند. هنگامی که برنامه تلاش می‌کند سرویسی را در پیش‌زمینه تبلیغ کند، سیستم مجوزهای مناسب را بررسی می‌کند و در صورت نداشتن برنامه، SecurityException پرتاب می‌کند. برای مثال، اگر می‌خواهید یک سرویس پیش‌زمینه از نوع location را راه‌اندازی کنید، سیستم بررسی می‌کند تا مطمئن شود برنامه شما قبلاً مجوز ACCESS_COARSE_LOCATION یا ACCESS_FINE_LOCATION را دارد. اسناد نوع خدمات پیش زمینه، پیش نیازهای مورد نیاز برای هر نوع خدمات پیش زمینه را فهرست می کند.

یک سرویس راه اندازی کنید

برای راه اندازی یک سرویس پیش زمینه، ابتدا باید آن را به عنوان یک سرویس معمولی (غیر پیش زمینه) راه اندازی کنید:

کاتلین

val intent = Intent(...) // Build the intent for the service
context.startForegroundService(intent)

جاوا

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 ) را ارسال کنید.

مثال زیر کدی را که یک سرویس دوربین برای تبلیغ خود به یک سرویس پیش زمینه استفاده می کند نشان می دهد:

کاتلین

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)
        }
        // ...
    }
  }
}

جاوا

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 نیاز دارد. با این حال، برنامه همچنین باید در زمان اجرا بررسی کند تا مطمئن شود کاربر این مجوز را اعطا کرده است. اگر برنامه واقعاً مجوزهای صحیح را ندارد، باید کاربر را از مشکل مطلع کند.
  • انواع مختلف خدمات پیش زمینه با نسخه های مختلف پلت فرم اندروید معرفی شدند. این کد بررسی می کند که روی چه نسخه ای از اندروید اجرا می شود و مجوزهای مناسب را درخواست می کند.
  • کد ForegroundServiceStartNotAllowedException را بررسی می کند، در صورتی که بخواهد یک سرویس پیش زمینه را در موقعیتی راه اندازی کند که مجاز نیست (به عنوان مثال، اگر سعی می کند سرویس را در پیش زمینه تبلیغ کند در حالی که برنامه در پس زمینه است ).