Meluncurkan layanan latar depan

Ada dua langkah untuk meluncurkan layanan latar depan dari aplikasi Anda. Pertama, Anda harus memulai layanan dengan memanggil context.startForegroundService(). Kemudian, minta layanan untuk memanggil ServiceCompat.startForeground() guna mempromosikan dirinya menjadi layanan latar depan.

Prasyarat

Bergantung pada API level yang ditargetkan aplikasi Anda, ada beberapa batasan tentang kapan aplikasi dapat meluncurkan layanan latar depan.

  • Aplikasi yang menargetkan Android 12 (API level 31) atau yang lebih tinggi tidak diizinkan untuk memulai layanan latar depan saat aplikasi berada di latar belakang, dengan beberapa pengecualian tertentu. Untuk informasi selengkapnya, dan informasi tentang pengecualian untuk aturan ini, lihat Pembatasan untuk memulai layanan latar depan dari latar belakang.

  • Aplikasi yang menargetkan Android 14 (API level 34) atau yang lebih tinggi harus meminta izin yang sesuai untuk jenis layanan latar depan. Saat aplikasi mencoba mempromosikan layanan ke latar depan, sistem akan memeriksa izin yang sesuai dan menampilkan SecurityException jika aplikasi tidak memilikinya. Misalnya, jika Anda mencoba meluncurkan layanan latar depan jenis location, sistem akan memeriksa untuk memastikan aplikasi Anda sudah memiliki izin ACCESS_COARSE_LOCATION atau ACCESS_FINE_LOCATION. Dokumentasi jenis layanan latar depan mencantumkan prasyarat yang diperlukan untuk setiap jenis layanan latar depan.

Meluncurkan layanan

Untuk meluncurkan layanan latar depan, Anda harus meluncurkannya terlebih dahulu sebagai layanan biasa (non-latar depan):

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

Poin penting tentang kode

  • Cuplikan kode meluncurkan layanan. Namun, layanan belum berjalan di latar depan. Di dalam layanan itu sendiri, Anda perlu memanggil ServiceCompat.startForeground() untuk mempromosikan layanan ke layanan latar depan.

Mempromosikan layanan ke latar depan

Setelah layanan berjalan, Anda perlu memanggil ServiceCompat.startForeground() untuk meminta layanan berjalan di latar depan. Biasanya, Anda akan memanggil metode ini dalam metode onStartCommand() layanan.

ServiceCompat.startForeground() menggunakan parameter berikut:

  • Layanan.
  • Bilangan bulat positif yang secara unik mengidentifikasi notifikasi layanan di status bar.
  • Objek Notification itu sendiri.
  • Jenis layanan latar depan yang mengidentifikasi pekerjaan yang dilakukan oleh layanan

Jenis layanan latar depan yang Anda teruskan ke startForeground() jenis yang dideklarasikan dalam manifes, bergantung pada kasus penggunaan tertentu. Kemudian, jika perlu menambahkan lebih banyak jenis layanan, Anda dapat memanggil startForeground() lagi.

Misalnya, aplikasi kebugaran menjalankan layanan pelacak lari yang selalu memerlukan informasi location, tetapi mungkin atau mungkin tidak perlu memutar media. Anda harus mendeklarasikan location dan mediaPlayback dalam manifes. Jika pengguna memulai lari dan hanya ingin lokasinya dilacak, aplikasi Anda harus memanggil startForeground() dan hanya meneruskan izin ACCESS_FINE_LOCATION. Kemudian, jika pengguna ingin mulai memutar audio, panggil startForeground() lagi dan teruskan kombinasi bitwise dari semua jenis layanan latar depan (dalam hal ini, ACCESS_FINE_LOCATION|FOREGROUND_SERVICE_MEDIA_PLAYBACK).

Contoh berikut menunjukkan kode yang akan digunakan layanan kamera untuk mempromosikan dirinya ke layanan latar depan:

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

    //...
}

Poin penting tentang kode

  • Aplikasi telah mendeklarasikan dalam manifes bahwa aplikasi memerlukan izin CAMERA. Namun, aplikasi juga harus memeriksa saat runtime untuk memastikan pengguna memberikan izin tersebut. Jika aplikasi sebenarnya tidak memiliki izin yang benar, aplikasi harus memberi tahu pengguna tentang masalah tersebut.
  • Berbagai jenis layanan latar depan diperkenalkan dengan versi platform Android yang berbeda. Kode ini memeriksa versi Android yang berjalan dan meminta izin yang sesuai.
  • Kode memeriksa ForegroundServiceStartNotAllowedException jika mencoba memulai layanan latar depan dalam situasi yang tidak diizinkan (misalnya, jika mencoba mempromosikan layanan ke latar depan saat aplikasi berada di latar belakang).