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

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

پیش‌نیازها

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

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

  • برنامه‌هایی که اندروید ۱۴ (سطح API ۳۴) یا بالاتر را هدف قرار می‌دهند، باید مجوزهای مناسب برای نوع سرویس پیش‌زمینه را درخواست کنند. هنگامی که برنامه سعی می‌کند یک سرویس را به پیش‌زمینه ارتقا دهد، سیستم مجوزهای مناسب را بررسی می‌کند و در صورت عدم وجود هرگونه مجوز، 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 را بررسی می‌کند.