Layanan latar depan

Layanan latar depan melakukan operasi yang dapat dilihat oleh pengguna.

Layanan latar depan menampilkan status bar notifikasi, untuk membuat pengguna menyadari bahwa aplikasi sedang menjalankan tugas di latar depan dan memakai sumber daya sistem.

Contoh aplikasi yang menggunakan layanan latar depan mencakup hal berikut:

  • Aplikasi pemutar musik yang memutar musik di layanan latar depan. Notifikasi mungkin menunjukkan lagu yang sedang diputar.
  • Aplikasi kebugaran yang merekam aktivitas lari pengguna di layanan latar depan, setelah menerima izin dari pengguna. Notifikasi mungkin menunjukkan jarak yang telah dilakukan pengguna selama sesi kebugaran saat ini.

Hanya menggunakan layanan latar depan saat aplikasi Anda perlu melakukan tugas yang dapat dilihat oleh pengguna, bahkan saat mereka tidak berinteraksi secara langsung dengan aplikasi. Jika tindakan tersebut memiliki kepentingan yang cukup rendah sehingga Anda ingin menggunakan notifikasi prioritas minimum, buat latar belakang tugas.

Dokumen ini menjelaskan izin yang diperlukan untuk menggunakan layanan latar depan, dan cara memulai layanan latar depan dan menghapusnya dari latar belakang. Ini juga menjelaskan cara mengaitkan kasus penggunaan tertentu dengan jenis layanan latar depan, dan batasan akses yang berlaku saat Anda memulai layanan latar depan dari aplikasi yang berjalan di latar belakang.

Pengguna dapat menutup notifikasi secara default

Mulai Android 13 (API level 33), pengguna dapat menutup notifikasi yang terkait dengan layanan latar depan secara default. Untuk melakukannya, pengguna menggeser pada notifikasi. Biasanya, notifikasi tidak ditutup kecuali jika layanan latar depan dihentikan atau dihapus dari latar depan.

Jika Anda ingin notifikasi tidak dapat ditutup oleh pengguna, teruskan true menuju setOngoing() saat Anda membuat notifikasi menggunakan Notification.Builder.

Layanan yang langsung menampilkan notifikasi

Jika layanan latar depan memiliki setidaknya salah satu dari karakteristik berikut, model menunjukkan notifikasi terkait segera setelah layanan dimulai, bahkan di perangkat yang menjalankan Android 12 atau yang lebih baru:

Di Android 13 (API level 33) atau yang lebih baru, jika pengguna menolak izin notifikasi, mereka masih melihat pemberitahuan terkait layanan latar depan di Pengelola Tugas namun jangan melihatnya di panel samping notifikasi.

Mendeklarasikan layanan latar depan dalam manifes

Dalam manifes aplikasi, deklarasikan setiap layanan latar depan aplikasi Anda dengan <service> . Untuk setiap layanan, gunakan Atribut android:foregroundServiceType untuk mendeklarasikan jenis pekerjaan yang dilakukan layanan.

Misalnya, jika aplikasi Anda membuat layanan latar depan yang memutar musik, Anda mungkin mendeklarasikan layanan seperti ini:

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

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

Jika beberapa jenis yang ada berlaku untuk layanan Anda, pisahkan dengan | operator. Misalnya, layanan yang menggunakan kamera dan mikrofon akan mendeklarasikannya seperti ini:

android:foregroundServiceType="camera|microphone"

Meminta izin layanan latar depan

Aplikasi yang menargetkan Android 9 (API level 28) atau yang lebih tinggi dan menggunakan layanan latar depan perlu meminta FOREGROUND_SERVICE di manifes aplikasi, seperti yang ditampilkan dalam cuplikan kode berikut. Ini adalah normal izin akses, sehingga sistem secara otomatis memberikannya ke aplikasi yang meminta.

Selain itu, jika aplikasi menargetkan API level 34 atau yang lebih tinggi, aplikasi harus meminta jenis izin yang sesuai untuk jenis pekerjaan yang akan digunakan di layanan latar depan lakukan. Setiap jenis layanan latar depan memiliki jenis izin yang sesuai. Misalnya, jika sebuah aplikasi meluncurkan layanan latar depan yang menggunakan kamera, Anda harus meminta FOREGROUND_SERVICE dan FOREGROUND_SERVICE_CAMERA izin akses. Ini semua adalah izin akses normal, jadi sistem memberikan izin secara otomatis jika mereka terdaftar dalam manifes.

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

Prasyarat layanan latar depan

Mulai Android 14 (API level 34), saat Anda meluncurkan layanan latar depan, sistem akan memeriksa prasyarat tertentu berdasarkan jenis layanan. Misalnya, jika Anda mencoba meluncurkan layanan latar depan jenis location, sistem akan memeriksa untuk memastikan aplikasi Anda sudah memiliki ACCESS_COARSE_LOCATION atau ACCESS_FINE_LOCATION. Jika tidak, sistem akan menampilkan SecurityException

Oleh karena itu, Anda harus mengonfirmasi bahwa prasyarat yang diperlukan telah terpenuhi sebelum memulai layanan latar depan. Layanan latar depan Dokumentasi jenis mencantumkan prasyarat yang diperlukan untuk setiap jenis layanan latar depan.

Memulai layanan latar depan

Sebelum Anda meminta sistem untuk menjalankan layanan sebagai layanan latar depan, layanan itu sendiri:

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

Di dalam layanan, biasanya di onStartCommand(), Anda dapat meminta yang membuat layanan Anda berjalan di latar depan. Untuk melakukannya, panggil ServiceCompat.startForeground() (tersedia di androidx-core 1.12 dan yang lebih tinggi). Metode ini mengambil beberapa hal berikut parameter:

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

Jenis ini mungkin merupakan subset dari jenis yang dideklarasikan dalam manifes, tergantung pada kasus penggunaan tertentu. Kemudian, jika Anda perlu menambahkan lebih banyak jenis layanan, Anda dapat memanggil startForeground() lagi.

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

Berikut adalah contoh yang meluncurkan layanan latar depan kamera:

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

    //...
}

Menghapus layanan dari latar depan

Untuk menghapus layanan dari latar depan, panggil stopForeground() Metode ini mengambil boolean, yang menunjukkan apakah status bar akan dihapus atau tidak notifikasi. Perhatikan bahwa layanan terus berjalan.

Jika Anda menghentikan layanan saat berjalan di latar depan, notifikasinya akan dihapus.

Menangani penghentian aplikasi yang dimulai oleh pengguna yang menjalankan layanan latar depan

Di bagian bawah panel samping notifikasi adalah tombol yang menunjukkan
    jumlah aplikasi yang sedang berjalan di latar belakang. Ketika Anda menekan
    tombol ini, dialog akan muncul, yang mencantumkan nama aplikasi yang berbeda. Tujuan
    Tombol berhenti ada di sebelah kanan setiap aplikasi
Gambar 1. Alur kerja Pengelola Tugas di perangkat yang menjalankan Android 13 atau yang lebih baru.

Mulai Android 13 (API level 33), pengguna dapat menyelesaikan alur kerja dari panel samping notifikasi untuk menghentikan aplikasi yang memiliki layanan latar depan yang sedang berlangsung, terlepas dari versi SDK target. Kemampuan ini, yang disebut Pengelola Tugas, menampilkan daftar aplikasi yang yang sedang menjalankan layanan latar depan.

Daftar ini diberi label Aplikasi aktif. Di samping setiap aplikasi terdapat tombol Berhenti. Gambar 1 mengilustrasikan Alur kerja Pengelola Tugas pada perangkat yang menjalankan Android 13.

Saat pengguna menekan tombol Stop di samping aplikasi Anda di Task Manager, maka tindakan berikut akan terjadi:

  • Sistem menghapus aplikasi Anda dari memori. Oleh karena itu, seluruh aplikasi Anda berhenti, bukan hanya layanan latar depan yang sedang berjalan.
  • Sistem menghapus data aktivitas aplikasi Anda sebelumnya.
  • Pemutaran media akan berhenti.
  • Notifikasi yang terkait dengan layanan latar depan dihapus.
  • Aplikasi Anda tetap berada dalam histori.
  • Tugas terjadwal dijalankan sesuai waktu yang dijadwalkan.
  • Alarm berbunyi pada waktu atau jendela waktu yang dijadwalkan.

Untuk menguji apakah aplikasi Anda berperilaku seperti yang diharapkan saat dan setelah pengguna menghentikan aplikasi aplikasi, jalankan perintah ADB berikut di jendela terminal:

adb shell cmd activity stop-app PACKAGE_NAME

Pengecualian

Sistem ini menyediakan beberapa tingkat pengecualian untuk jenis aplikasi tertentu, yang dijelaskan di bagian berikut.

Pengecualian berlaku per aplikasi, bukan per proses. Jika sistem mengecualikan satu proses dalam sebuah aplikasi, semua proses lain dalam aplikasi tersebut juga akan dikecualikan.

Pengecualian agar tidak muncul di Task Manager sama sekali

Aplikasi berikut dapat menjalankan layanan latar depan dan tidak muncul di {i>Task Manager<i}:

  • Aplikasi tingkat sistem
  • Aplikasi keselamatan; yaitu, aplikasi yang memiliki peran ROLE_EMERGENCY
  • Perangkat yang menggunakan mode demo

Pengecualian agar tidak dapat dihentikan oleh pengguna

Saat jenis aplikasi berikut menjalankan layanan latar depan, aplikasi tersebut akan muncul di Task Manager, tetapi tidak ada tombol Stop di samping nama aplikasi yang akan diketuk oleh pengguna:

Menggunakan API yang dibuat khusus, bukan layanan latar depan

Untuk banyak kasus penggunaan, ada platform atau Jetpack API yang dapat Anda gunakan untuk melakukan pekerjaan Anda mungkin perlu menggunakan layanan latar depan. Jika ada pendekatan API yang dibuat khusus, Anda harus hampir selalu menggunakannya daripada menggunakan layanan. API yang dibuat khusus sering kali menyediakan kasus penggunaan tambahan yang biasanya harus Anda bangun sendiri. Misalnya, Bubbles API menangani logika UI yang kompleks untuk aplikasi pesan yang perlu mengimplementasikan fitur gelembung obrolan.

Dokumentasi untuk daftar jenis layanan latar depan alternatif yang baik untuk digunakan sebagai ganti layanan latar depan.

Batasan dalam memulai layanan latar depan dari latar belakang

Aplikasi yang menargetkan Android 12 atau yang lebih tinggi tidak dapat memulai latar depan saat aplikasi berjalan di latar belakang, kecuali untuk beberapa hal khusus kasus. Jika aplikasi mencoba memulai layanan latar depan saat aplikasi berjalan di latar belakang, dan di latar depan tertentu tidak memenuhi salah satu kasus luar biasa, sistem akan menampilkan ForegroundServiceStartNotAllowedException

Selain itu, jika aplikasi ingin meluncurkan layanan latar depan yang membutuhkan Izin saat digunakan (misalnya, sensor tubuh, kamera, mikrofon, atau lokasi izin), aplikasi tidak dapat membuat layanan saat aplikasi berada di latar belakang, meskipun aplikasi termasuk dalam salah satu pengecualian dari awal di latar belakang pembatasan. Alasannya dijelaskan di bagian Batasan memulai layanan latar depan yang perlu digunakan saat digunakan izin akses.

Pengecualian dari pembatasan memulai di latar belakang

Dalam situasi berikut, aplikasi Anda dapat memulai layanan latar depan bahkan saat aplikasi Anda berjalan di latar belakang:

Batasan dalam memulai layanan latar depan yang memerlukan izin saat digunakan

Di Android 14 (level API 34) atau yang lebih baru, ada situasi khusus yang perlu diperhatikan jika Anda memulai layanan latar depan yang memerlukan izin saat digunakan.

Jika aplikasi Anda menargetkan Android 14 atau yang lebih baru, sistem operasi memeriksa saat Anda membuat layanan latar depan untuk memastikan aplikasi Anda memiliki semua izin akses yang sesuai untuk jenis layanan tersebut. Misalnya, saat Anda membuat layanan latar depan jenis mikrofon, sistem operasi memverifikasi bahwa aplikasi Anda saat ini memiliki RECORD_AUDIO izin akses. Jika Anda tidak memiliki izin tersebut, sistem akan menampilkan SecurityException

Untuk izin saat sedang digunakan, hal ini berpotensi menimbulkan masalah. Jika aplikasi Anda memiliki izin akses saat sedang digunakan, aplikasi hanya memiliki izin tersebut saat berada dalam latar depan. Artinya, jika aplikasi berada di latar belakang, dan mencoba membuat layanan latar depan jenis kamera, lokasi, atau mikrofon, sistem melihat bahwa aplikasi Anda saat ini tidak memiliki izin yang diperlukan, dan akan menampilkan SecurityException.

Demikian pula, jika aplikasi Anda berada di latar belakang dan membuat layanan kesehatan yang memerlukan izin BODY_SENSORS_BACKGROUND, aplikasi saat ini belum memiliki izin tersebut, dan sistem akan menampilkan pengecualian. (Hal ini tidak berlaku jika untuk layanan kesehatan yang memerlukan izin yang berbeda, seperti ACTIVITY_RECOGNITION.) Menelepon PermissionChecker.checkSelfPermission() tidak mencegah masalah ini. Jika aplikasi Anda memiliki izin saat digunakan, dan metode memanggil checkSelfPermission() untuk memeriksa apakah memiliki izin tersebut. menampilkan PERMISSION_GRANTED meskipun aplikasi berada di latar belakang. Jika metode menampilkan PERMISSION_GRANTED, yang mengatakan "aplikasi Anda memiliki izin ini saat aplikasi digunakan."

Untuk alasan ini, jika layanan latar depan memerlukan izin saat digunakan, Anda harus memanggil Context.startForegroundService() atau Context.bindService() saat aplikasi Anda memiliki aktivitas yang terlihat, kecuali jika layanan termasuk dalam salah satu pengecualian yang ditentukan.

Pengecualian dari pembatasan izin saat digunakan

Dalam beberapa situasi, meskipun layanan latar depan dimulai saat aplikasi berjalan di latar belakang, aplikasi masih dapat mengakses lokasi, informasi kamera, dan mikrofon saat aplikasi berjalan di latar depan ("saat digunakan").

Dalam situasi yang sama, jika layanan mendeklarasikan jenis layanan latar depan location dan dimulai oleh aplikasi yang memiliki ACCESS_BACKGROUND_LOCATION izin akses, layanan ini dapat mengakses informasi lokasi sepanjang waktu, bahkan ketika aplikasi berjalan di latar belakang.

Daftar berikut berisi situasi berikut:

  • Komponen sistem memulai layanan.
  • Layanan dimulai dengan berinteraksi dengan aplikasi widget.
  • Layanan dimulai dengan berinteraksi dengan notifikasi.
  • Layanan ini dimulai sebagai PendingIntent yang dikirim dari aplikasi yang berbeda dan terlihat.
  • Layanan dimulai oleh aplikasi yang merupakan kebijakan perangkat pengontrol yang berjalan dalam mode pemilik perangkat.
  • Layanan dimulai oleh aplikasi yang menyediakan VoiceInteractionService.
  • Layanan dimulai oleh aplikasi yang memiliki START_ACTIVITIES_FROM_BACKGROUND izin hak istimewa.
Menentukan layanan yang terpengaruh di aplikasi Anda

Saat menguji aplikasi Anda, mulai layanan latar depannya. Jika layanan yang dimulai memiliki akses terbatas ke lokasi, mikrofon, dan kamera, pesan berikut akan muncul di Logcat:

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