Service
adalah
komponen aplikasi yang dapat menjalankan
yang berjalan lama di latar belakang. Tidak menyediakan antarmuka pengguna. Satu kali
dimulai, layanan mungkin terus berjalan untuk beberapa waktu, bahkan setelah pengguna beralih ke
aplikasi. Selain itu, komponen bisa mengikat ke layanan
untuk berinteraksi dengannya dan bahkan melakukan
komunikasi antarproses (IPC). Misalnya, layanan dapat menangani
transaksi jaringan, memutar
musik, menjalankan I/O file, atau berinteraksi dengan penyedia konten, semuanya dari latar belakang.
Perhatian: Layanan berjalan di thread utama hosting-nya proses; layanan tidak membuat threadnya sendiri dan tidak yang berjalan dalam proses terpisah kecuali Anda menentukan sebaliknya. Anda harus menjalankan setiap operasi pemblokiran di thread terpisah dalam layanan untuk menghindari Aplikasi Error Tidak Merespons (ANR).
Jenis Layanan
Inilah tiga tipe layanan yang berbeda:
- Latar depan
-
Layanan latar depan melakukan beberapa operasi yang terlihat oleh . Misalnya, aplikasi audio akan menggunakan layanan latar depan untuk memutar trek audio. Layanan latar depan harus menampilkan Notifikasi. Layanan latar depan terus berjalan meskipun pengguna tidak berinteraksi dengan aplikasi.
Saat menggunakan layanan latar depan, Anda harus menampilkan notifikasi agar pengguna secara aktif menyadari bahwa layanan sedang berjalan. Notifikasi ini tidak dapat akan ditutup kecuali jika layanan dihentikan atau dihapus dari latar depan.
Pelajari lebih lanjut cara mengonfigurasi layanan latar depan di .
Catatan: WorkManager API menawarkan cara yang fleksibel untuk menjadwalkan tugas, dan mampu menjalankan tugas ini sebagai layanan latar depan jika diperlukan. Dalam banyak kasus, menggunakan WorkManager lebih disarankan daripada menggunakan layanan latar depan secara langsung.
- Latar belakang
- Layanan latar belakang melakukan operasi yang tidak terlihat secara langsung oleh
pengguna. Misalnya, jika sebuah aplikasi menggunakan
layanan untuk memadatkan penyimpanannya,
yang biasanya akan menjadi
layanan latar belakang.
Catatan: Jika aplikasi Anda menargetkan API level 26 atau yang lebih tinggi, sistem akan menerapkan batasan untuk menjalankan latar belakang layanan saat aplikasi itu sendiri tidak ada di latar depan. Dalam sebagian besar Misalnya, Anda seharusnya tidak mengakses informasi lokasi dari latar belakang. Sebagai gantinya, menjadwalkan tugas menggunakan WorkManager.
- Terikat
- Layanan terikat saat komponen aplikasi mengikatnya dengan memanggil
bindService()
. Layanan terikat menawarkan layanan klien-server antarmuka yang memungkinkan komponen untuk berinteraksi dengan layanan, mengirim permintaan, menerima hasil, dan bahkan melakukannya di seluruh proses dengan komunikasi antarproses (IPC). Layanan terikat hanya berjalan selama komponen aplikasi lain terikat padanya. Beberapa komponen bisa terikat ke layanan sekaligus, tetapi ketika semuanya melepaskan ikatan, layanan itu akan dihancurkan.
Meskipun dokumentasi ini umumnya membahas
layanan yang dimulai dan terikat secara terpisah,
layanan Anda dapat berfungsi dengan dua cara—layanan dapat dimulai (untuk berjalan tanpa batas waktu) dan juga memungkinkan
jaringan. Ini hanya masalah apakah Anda mengimplementasikan beberapa metode callback: onStartCommand()
untuk mengizinkan komponen memulainya dan onBind()
untuk memungkinkan binding.
Terlepas dari apakah layanan Anda dimulai, terikat, atau keduanya, komponen aplikasi apa pun
dapat menggunakan layanan (bahkan dari aplikasi terpisah) dengan cara yang sama seperti yang bisa digunakan komponen
aktivitas—dengan memulainya menggunakan Intent
. Namun, Anda dapat mendeklarasikan
membuat layanan sebagai pribadi dalam file manifes dan memblokir akses dari aplikasi lain.
Hal ini dibahas lebih lanjut di bagian tentang Mendeklarasikan layanan dalam
manifes.
Memilih antara layanan dan thread
Layanan hanyalah komponen yang bisa berjalan di latar belakang, bahkan saat pengguna tidak berinteraksi dengan aplikasi Anda, jadi sebaiknya Anda membuat layanan hanya jika itu yang butuhkan.
Jika Anda harus melakukan pekerjaan di luar thread utama, tetapi hanya saat pengguna berinteraksi
dengan aplikasi Anda, sebaiknya buat thread baru dalam konteks aplikasi lain
komponen. Misalnya, jika Anda ingin memutar musik, tetapi hanya saat aktivitas sedang berjalan,
Anda dapat membuat thread di onCreate()
,
mulai menjalankannya dalam onStart()
,
dan hentikan di onStop()
.
Pertimbangkan juga untuk menggunakan kumpulan thread dan eksekutor dari paket java.util.concurrent
atau coroutine Kotlin, bukan metode
Class Thread
. Lihat
Dokumen Threading di Android untuk informasi selengkapnya tentang
memindahkan eksekusi ke thread latar belakang.
Ingatlah bahwa jika Anda menggunakan layanan, layanan itu masih berjalan di thread utama aplikasi dengan {i>default<i}, jadi Anda tetap harus membuat {i>thread <i}baru dalam layanan jika layanan itu bekerja secara intensif operasi pemblokiran.
Dasar-dasar
Untuk membuat layanan, Anda harus membuat subclass dari Service
atau menggunakannya
dari subclass yang sudah ada. Dalam implementasi, Anda harus mengganti beberapa metode callback yang
menangani aspek kunci dari siklus hidup layanan dan
menyediakan mekanisme yang memungkinkan komponen
mengikat ke layanan, jika sesuai. Ini adalah metode callback paling penting yang harus Anda
penggantian:
onStartCommand()
- Sistem memanggil metode ini dengan memanggil
startService()
saat komponen lain (seperti aktivitas) meminta agar layanan dimulai. Ketika metode ini dieksekusi, layanan akan dimulai dan dapat berjalan di latar belakang tanpa batas waktu. Jika Anda menerapkan ini, Anda bertanggung jawab untuk menghentikan layanan saat pekerjaannya akan diselesaikan dengan memanggilstopSelf()
ataustopService()
. Jika Anda hanya ingin menyediakan pengikatan, Anda tidak mengimplementasikan metode ini. onBind()
- Sistem memanggil metode ini dengan memanggil
bindService()
saat komponen lain ingin mengikat dengan layanan (seperti untuk menjalankan RPC). Dalam implementasi metode ini, Anda harus menyediakan antarmuka yang gunakan untuk berkomunikasi dengan layanan dengan menampilkanIBinder
. Anda harus selalu mengimplementasikan metode ini; Namun, jika tidak ingin mengizinkan pengikatan, Anda harus mengembalikan null. onCreate()
- Sistem akan memanggil metode ini untuk melakukan prosedur penyiapan satu kali saat layanan
pertama kali dibuat (sebelum memanggil
onStartCommand()
atauonBind()
). Jika layanan sudah berjalan, metode ini belum dipanggil. onDestroy()
- Sistem memanggil metode ini saat layanan tidak lagi digunakan dan sedang dihancurkan. Layanan Anda harus mengimplementasikannya untuk membersihkan resource seperti thread, yang terdaftar pemroses, atau penerima. Ini adalah panggilan terakhir yang diterima layanan.
Jika komponen memulai layanan dengan memanggil startService()
(yang menghasilkan panggilan ke onStartCommand()
), layanan tersebut
terus berjalan sampai berhenti sendiri dengan stopSelf()
atau yang lainnya
menghentikannya dengan memanggil stopService()
.
Jika komponen memanggil
bindService()
untuk membuat layanan dan onStartCommand()
tidak dipanggil, layanan akan berjalan
selama komponen terikat padanya. Setelah layanan dilepas ikatannya
dari semua kliennya,
sistem akan menghancurkannya.
Sistem Android menghentikan layanan hanya jika memori tinggal sedikit dan sistem harus memulihkan sistem
sumber daya untuk aktivitas yang mendapatkan fokus pengguna. Jika layanan terikat ke aktivitas yang memiliki
fokus, kecil kemungkinannya
terbunuh; jika layanan dideklarasikan untuk berjalan di latar depan, layanan jarang dihentikan.
Jika layanan dimulai dan berjalan lama, sistem akan menurunkan posisinya
dalam daftar tugas latar belakang dari waktu ke waktu, dan layanan menjadi sangat rentan terhadap
killing—jika layanan dimulai, Anda harus mendesainnya agar dapat menangani mulai ulang dengan baik
oleh sistem. Jika sistem mematikan layanan Anda, layanan akan dimulai ulang begitu resource menjadi
tersedia, tetapi ini juga bergantung pada nilai yang Anda tampilkan dari onStartCommand()
. Untuk informasi lebih lanjut
kapan sistem mungkin akan menghancurkan layanan, lihat Proses dan Threading
dokumen.
Di bagian berikut, Anda akan melihat cara membuat
startService()
dan
Metode layanan bindService()
, serta cara menggunakan
mereka dari komponen aplikasi lainnya.
Mendeklarasikan layanan dalam manifes
Anda harus mendeklarasikan semua layanan dalam seperti yang Anda lakukan untuk aktivitas dan komponen lainnya.
Untuk mendeklarasikan layanan Anda, tambahkan elemen <service>
sebagai turunan dari <application>
. Berikut ini contohnya:
<manifest ... > ... <application ... > <service android:name=".ExampleService" /> ... </application> </manifest>
Lihat elemen <service>
untuk informasi selengkapnya tentang mendeklarasikan layanan dalam manifes.
Ada atribut lain yang dapat Anda sertakan dalam elemen <service>
untuk
menentukan properti seperti izin yang diperlukan untuk memulai layanan dan proses dalam
layanan yang harus dijalankan. android:name
adalah satu-satunya atribut yang diperlukan—atribut ini menentukan nama class layanan. Sesudah
Anda memublikasikan aplikasi, jangan ubah nama ini untuk menghindari risiko kerusakan
kode karena ketergantungan pada intent eksplisit untuk memulai atau mengikat layanan (baca postingan blog, Things
Itu Tidak Dapat Diubah).
Perhatian: Untuk memastikan aplikasi Anda aman, selalu gunakan
intent eksplisit saat memulai Service
dan tidak mendeklarasikan filter intent untuk
layanan Anda. Menggunakan intent implisit untuk memulai layanan dapat menimbulkan bahaya keamanan karena Anda tidak bisa
memastikan layanan yang merespons intent tersebut, dan pengguna tidak bisa melihat layanan mana
memulai. Mulai dari Android 5.0 (API level 21), sistem akan menampilkan pengecualian jika Anda memanggil
bindService()
dengan intent implisit.
Anda dapat memastikan bahwa layanan hanya tersedia untuk aplikasi Anda dengan
termasuk android:exported
dan menyetelnya ke false
. Tindakan ini secara efektif menghentikan aplikasi lain memulai
gratis, bahkan saat menggunakan intent eksplisit.
Catatan:
Pengguna dapat melihat layanan yang sedang berjalan di perangkat mereka. Jika mereka melihat
layanan yang tidak mereka kenali atau
percaya, mereka dapat menghentikan layanan itu. Di beberapa
untuk menghindari layanan Anda dihentikan secara
tidak sengaja oleh pengguna, Anda perlu
untuk menambahkan
android:description
ke atribut
<service>
di manifes aplikasi Anda. Dalam deskripsi,
berikan kalimat singkat yang menjelaskan hal yang dilakukan layanan dan manfaatnya
yang dihasilkannya.
Membuat layanan yang sudah dimulai
Layanan yang sudah dimulai adalah layanan yang dimulai komponen lain dengan memanggil startService()
, yang menghasilkan panggilan ke layanan
Metode onStartCommand()
.
Ketika layanan dimulai, layanan tersebut memiliki
siklus hidup yang tidak bergantung pada
dasar yang memulainya. Layanan bisa berjalan di latar belakang tanpa batas waktu, meskipun
komponen yang memulainya akan dihancurkan. Dengan demikian, layanan itu harus berhenti sendiri saat tugasnya
diselesaikan dengan memanggil stopSelf()
, atau komponen lain dapat
hentikan dengan memanggil stopService()
.
Komponen aplikasi seperti aktivitas dapat memulai layanan dengan memanggil startService()
dan meneruskan Intent
yang menentukan layanan dan mencakup data yang akan digunakan oleh layanan. Layanan menerima
Intent
ini dalam metode onStartCommand()
.
Sebagai contoh, anggaplah aktivitas perlu menyimpan data ke database online. Aktivitas
dapat memulai layanan pendamping dan mengirimkan data untuk disimpan dengan meneruskan intent ke startService()
. Layanan akan menerima intent di onStartCommand()
, menghubungkan ke Internet, dan melakukan
untuk transaksi {i>database<i}. Ketika transaksi selesai, layanan berhenti sendiri dan
dihancurkan.
Perhatian: Layanan berjalan dalam proses yang sama dengan aplikasi tempat variabel tersebut dideklarasikan dan di thread utama aplikasi tersebut secara default. Jika layanan Anda melakukan operasi intensif atau pemblokir saat pengguna berinteraksi dengan aktivitas dari aplikasi, layanan akan memperlambat kinerja aktivitas. Agar tidak memengaruhi aplikasi menjalankan thread baru di dalam layanan.
Class Service
adalah dasar
untuk semua layanan. Saat Anda memperluas class ini, penting untuk membuat thread baru tempat
layanan dapat menyelesaikan
semua pekerjaannya; layanan ini menggunakan thread utama aplikasi Anda dengan
secara default, yang dapat memperlambat kinerja aktivitas apa pun yang sedang dijalankan aplikasi.
Framework Android juga menyediakan IntentService
subclass dari Service
yang menggunakan
untuk menangani semua permintaan memulai, satu per satu. Menggunakan kelas ini tidak
direkomendasikan untuk aplikasi baru karena aplikasi tersebut tidak akan berfungsi dengan baik mulai dengan Android 8 Oreo, karena
pengenalan Batas eksekusi latar belakang.
Selain itu, fitur ini tidak digunakan lagi mulai dari Android 11.
Anda dapat menggunakan JobWorkRequest sebagai
untuk IntentService
yang kompatibel dengan versi Android yang lebih baru.
Bagian berikut menjelaskan cara menerapkan layanan kustom Anda sendiri, tetapi Anda harus pertimbangkan untuk menggunakan WorkManager untuk sebagian besar kasus penggunaan. Baca panduan pemrosesan latar belakang di Android untuk melihat apakah ada solusi yang sesuai dengan kebutuhan Anda.
Memperluas class Layanan
Anda dapat memperluas class Service
untuk menangani setiap intent yang masuk. Berikut adalah tampilan implementasi dasar:
Kotlin
class HelloService : Service() { private var serviceLooper: Looper? = null private var serviceHandler: ServiceHandler? = null // Handler that receives messages from the thread private inner class ServiceHandler(looper: Looper) : Handler(looper) { override fun handleMessage(msg: Message) { // Normally we would do some work here, like download a file. // For our sample, we just sleep for 5 seconds. try { Thread.sleep(5000) } catch (e: InterruptedException) { // Restore interrupt status. Thread.currentThread().interrupt() } // Stop the service using the startId, so that we don't stop // the service in the middle of handling another job stopSelf(msg.arg1) } } override fun onCreate() { // Start up the thread running the service. Note that we create a // separate thread because the service normally runs in the process's // main thread, which we don't want to block. We also make it // background priority so CPU-intensive work will not disrupt our UI. HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND).apply { start() // Get the HandlerThread's Looper and use it for our Handler serviceLooper = looper serviceHandler = ServiceHandler(looper) } } override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show() // For each start request, send a message to start a job and deliver the // start ID so we know which request we're stopping when we finish the job serviceHandler?.obtainMessage()?.also { msg -> msg.arg1 = startId serviceHandler?.sendMessage(msg) } // If we get killed, after returning from here, restart return START_STICKY } override fun onBind(intent: Intent): IBinder? { // We don't provide binding, so return null return null } override fun onDestroy() { Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show() } }
Java
public class HelloService extends Service { private Looper serviceLooper; private ServiceHandler serviceHandler; // Handler that receives messages from the thread private final class ServiceHandler extends Handler { public ServiceHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { // Normally we would do some work here, like download a file. // For our sample, we just sleep for 5 seconds. try { Thread.sleep(5000); } catch (InterruptedException e) { // Restore interrupt status. Thread.currentThread().interrupt(); } // Stop the service using the startId, so that we don't stop // the service in the middle of handling another job stopSelf(msg.arg1); } } @Override public void onCreate() { // Start up the thread running the service. Note that we create a // separate thread because the service normally runs in the process's // main thread, which we don't want to block. We also make it // background priority so CPU-intensive work doesn't disrupt our UI. HandlerThread thread = new HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND); thread.start(); // Get the HandlerThread's Looper and use it for our Handler serviceLooper = thread.getLooper(); serviceHandler = new ServiceHandler(serviceLooper); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show(); // For each start request, send a message to start a job and deliver the // start ID so we know which request we're stopping when we finish the job Message msg = serviceHandler.obtainMessage(); msg.arg1 = startId; serviceHandler.sendMessage(msg); // If we get killed, after returning from here, restart return START_STICKY; } @Override public IBinder onBind(Intent intent) { // We don't provide binding, so return null return null; } @Override public void onDestroy() { Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show(); } }
Kode contoh menangani semua panggilan masuk di onStartCommand()
dan memposting pekerjaan ke Handler
yang berjalan di thread latar belakang. Fungsi ini berfungsi seperti IntentService
dan memproses semua permintaan secara serial, satu per satu.
Anda dapat mengubah kode untuk menjalankan tugas di kumpulan thread, misalnya, jika ingin menjalankan beberapa permintaan secara bersamaan.
Perhatikan bahwa metode onStartCommand()
harus menampilkan
bilangan bulat. Bilangan bulat adalah nilai yang menjelaskan bagaimana sistem harus melanjutkan layanan dalam
yang kemudian dimatikan
oleh sistem. Nilai yang ditampilkan
dari onStartCommand()
harus berupa salah satu dari hal berikut
konstanta:
START_NOT_STICKY
- Jika sistem mematikan layanan setelah
onStartCommand()
ditampilkan, jangan membuat ulang layanan kecuali jika ada yang ingin dicapai. Ini adalah opsi paling aman agar layanan tidak dijalankan saat tidak diperlukan dan kapan aplikasi Anda bisa memulai ulang tugas yang belum selesai. START_STICKY
- Jika sistem mematikan layanan setelah
onStartCommand()
ditampilkan, buat ulang layanan dan panggilonStartCommand()
, tetapi jangan kirim ulang intent terakhir. Sebagai gantinya, sistem akan memanggilonStartCommand()
dengan intent null kecuali jika ada intent yang tertunda untuk memulai layanan. Dalam kasus tersebut, semua intent tersebut dikirim. Ini cocok untuk pemutar media (atau layanan serupa) yang tidak mengeksekusi perintah tetapi berjalan terus-menerus dan menunggu tugas. START_REDELIVER_INTENT
- Jika sistem mematikan layanan setelah
onStartCommand()
ditampilkan, buat ulang layanan dan panggilonStartCommand()
dengan intent terakhir yang dikirimkan ke layanan. Intent yang tertunda akan disampaikan pada gilirannya. Ini cocok untuk layanan yang melakukan tugas yang harus segera dilanjutkan, misalnya mengunduh file.
Untuk detail selengkapnya tentang nilai yang ditampilkan ini, lihat referensi tertaut untuk setiap konstanta.
Memulai layanan
Anda bisa memulai layanan dari aktivitas atau komponen aplikasi lain dengan
meneruskan Intent
ke startService()
atau startForegroundService()
. Tujuan
Sistem Android memanggil metode onStartCommand()
layanan dan meneruskan Intent
ke metode tersebut,
yang menentukan layanan
mana yang akan dimulai.
Catatan: Jika aplikasi Anda menargetkan API level 26 atau yang lebih tinggi, sistem
memberlakukan batasan pada penggunaan atau pembuatan layanan latar belakang kecuali aplikasi
berada di latar depan. Jika aplikasi perlu membuat
layanan latar depan,
aplikasi harus memanggil startForegroundService()
. Metode itu membuat layanan latar belakang, tapi
memberi sinyal ke sistem bahwa layanan
akan mempromosikan dirinya sendiri ke
latar depan. Setelah dibuat, layanan harus memanggil
startForeground()
metode dalam
lima detik.
Misalnya, aktivitas dapat memulai layanan contoh di bagian sebelumnya (HelloService
) menggunakan intent eksplisit dengan startService()
, seperti yang ditampilkan di sini:
Kotlin
startService(Intent(this, HelloService::class.java))
Java
startService(new Intent(this, HelloService.class));
Metode startService()
langsung ditampilkan, dan
sistem Android memanggil metode onStartCommand()
layanan. Jika layanan belum berjalan, sistem akan memanggil onCreate()
terlebih dahulu, lalu memanggil
onStartCommand()
.
Jika layanan juga tidak menyediakan binding, intent yang dikirimkan dengan startService()
adalah satu-satunya mode komunikasi antara
komponen aplikasi dan layanan. Namun, jika Anda ingin layanan
mengirimkan hasil kembali,
klien yang memulai layanan dapat membuat PendingIntent
untuk siaran
(dengan getBroadcast()
) dan mengirimkannya ke layanan
di Intent
yang memulai layanan. Layanan kemudian dapat menggunakan
untuk menyampaikan hasil.
Beberapa permintaan untuk memulai layanan menghasilkan beberapa panggilan yang sesuai ke metode
onStartCommand()
. Namun, hanya satu permintaan untuk menghentikan
layanan (dengan stopSelf()
atau stopService()
) diperlukan untuk menghentikannya.
Menghentikan layanan
Layanan yang sudah dimulai harus mengelola daur hidupnya sendiri. Artinya, sistem tidak
berhenti atau
menghancurkan layanan kecuali jika harus
memulihkan memori sistem dan layanan
terus berjalan setelah onStartCommand()
ditampilkan. Tujuan
layanan harus berhenti sendiri dengan memanggil stopSelf()
, atau yang lainnya
yang berbeda dapat menghentikannya dengan memanggil stopService()
.
Setelah diminta untuk berhenti dengan stopSelf()
atau stopService()
, sistem akan menghancurkan layanan begitu
sebaik mungkin.
Jika layanan Anda menangani beberapa permintaan ke onStartCommand()
secara serentak, Anda tidak boleh menghentikan metode
setelah selesai memproses permintaan memulai, karena Anda mungkin telah menerima
memulai permintaan (berhenti di akhir permintaan pertama akan menghentikan permintaan kedua). Untuk menghindari
masalah ini, Anda dapat menggunakan stopSelf(int)
untuk memastikan bahwa permintaan Anda
menghentikan layanan selalu didasarkan
pada permintaan mulai terbaru. Artinya, saat memanggil stopSelf(int)
, Anda meneruskan ID permintaan memulai (startId
dikirim ke onStartCommand()
) yang menjadi tujuan permintaan perhentian Anda
sesuai. Kemudian, jika layanan menerima permintaan memulai baru sebelum Anda dapat memanggil stopSelf(int)
, ID tidak akan cocok dan layanan tidak berhenti.
Perhatian: Untuk menghindari pemborosan resource sistem dan konsumsi
daya baterai, pastikan aplikasi Anda menghentikan layanannya bila sudah selesai bekerja.
Jika perlu, komponen lain dapat menghentikan layanan dengan memanggil stopService()
. Bahkan jika Anda mengaktifkan
pengikatan untuk layanan,
Anda harus selalu menghentikan layanan sendiri jika pernah menerima panggilan ke onStartCommand()
.
Untuk informasi selengkapnya tentang siklus proses layanan, lihat bagian di bawah tentang Mengelola Siklus Proses Layanan.
Membuat layanan terikat
Layanan terikat adalah layanan yang memungkinkan komponen aplikasi mengikatnya dengan memanggil bindService()
untuk membuat koneksi jangka panjang.
Opsi ini biasanya tidak mengizinkan komponen untuk memulainya dengan memanggil startService()
.
Membuat layanan terikat jika Anda ingin berinteraksi dengan layanan dari aktivitas dan komponen lainnya dalam aplikasi Anda atau untuk mengekspos beberapa fungsi aplikasi Anda ke aplikasi lain melalui komunikasi antarproses (IPC).
Untuk membuat layanan terikat, terapkan metode callback onBind()
untuk menampilkan IBinder
yang
mendefinisikan antarmuka untuk komunikasi dengan layanan. Komponen aplikasi lain kemudian
dapat memanggil
bindService()
untuk mengambil antarmuka dan
mulai memanggil metode pada layanan. Layanan hanya hidup untuk menyajikan komponen aplikasi yang
terikat padanya, sehingga bila tidak ada komponen yang terikat pada layanan, sistem akan menghancurkannya.
Anda tidak perlu menghentikan layanan terikat dengan cara yang sama seperti yang Anda lakukan saat layanan
dimulai sampai onStartCommand()
.
Untuk membuat layanan terikat, Anda harus mendefinisikan antarmuka yang menetapkan cara klien
berkomunikasi dengan layanan. Antarmuka antara layanan ini
dan klien harus berupa implementasi dari IBinder
dan merupakan hal yang harus
tampilkan dari metode callback onBind()
. Setelah menerima IBinder
, klien dapat memulai
berinteraksi dengan layanan
melalui antarmuka tersebut.
Beberapa klien bisa mengikat ke layanan sekaligus. Saat klien selesai berinteraksi dengan
layanan, kode itu memanggil unbindService()
untuk melepas ikatan.
Bila tidak ada klien yang terikat pada layanan, sistem akan menghapus layanan tersebut.
Ada beberapa cara untuk mengimplementasikan layanan terikat, dan implementasinya lebih rumit dibandingkan layanan yang sudah dimulai. Karena alasan ini, diskusi layanan terikat muncul di dokumen terpisah tentang Layanan Terikat.
Mengirim notifikasi ke pengguna
Saat sedang berjalan, layanan dapat memberi tahu pengguna tentang peristiwa menggunakan notifikasi camilan atau notifikasi status bar.
Notifikasi snackbar adalah pesan yang muncul di permukaan jendela saat ini hanya untuk sebelum menghilang. Notifikasi bilah status menyediakan ikon di bilah status dengan pesan, yang dapat dipilih pengguna untuk melakukan tindakan (seperti memulai aktivitas).
Biasanya, notifikasi bilah status adalah teknik terbaik yang digunakan saat pekerjaan latar belakang seperti unduhan file telah selesai, dan pengguna sekarang dapat bertindak. Saat pengguna memilih notifikasi dari tampilan yang diperluas, notifikasi dapat memulai aktivitas (seperti untuk menampilkan file yang didownload).
Mengelola daur hidup layanan
Daur hidup layanan jauh lebih sederhana daripada daur hidup aktivitas. Namun, lebih Anda harus memperhatikan dengan cermat bagaimana layanan Anda dibuat dan dihancurkan karena layanan dapat berjalan di latar belakang tanpa disadari oleh pengguna.
Siklus proses layanan—dari saat dibuat hingga dihancurkan—dapat mengikuti salah satu dari kedua jalur ini:
- Layanan yang sudah dimulai
Layanan dibuat saat komponen lain memanggil
startService()
. Layanan kemudian berjalan tanpa batas waktu dan harus menghentikan dirinya sendiri dengan memanggilstopSelf()
. Komponen lain juga dapat menghentikan layanan Google dengan memanggilstopService()
. Bila layanan dihentikan, sistem akan memusnahkannya. - Layanan terikat
Layanan dibuat saat komponen lain (klien) memanggil
bindService()
. Klien kemudian berkomunikasi dengan layanan melalui antarmukaIBinder
. Klien dapat memutus koneksi dengan memanggilunbindService()
. Beberapa klien dapat mengikat layanan yang sama dan ketika semuanya melepas ikatan, sistem menghancurkan layanan itu. Layanan tidak perlu berhenti sendiri.
Kedua jalur ini tidak sepenuhnya terpisah. Anda dapat mengikat
ke layanan yang sudah
dimulai dengan startService()
. Sebagai contoh, Anda dapat
memulai layanan musik latar belakang dengan memanggil startService()
dengan Intent
yang mengidentifikasi musik yang akan diputar. Kemudian,
mungkin ketika pengguna ingin mengontrol
pemain atau mendapatkan informasi tentang
lagu saat ini, aktivitas dapat mengikat ke layanan dengan memanggil bindService()
. Dalam kasus seperti ini, stopService()
atau stopSelf()
tidak benar-benar menghentikan layanan hingga semua klien melepas ikatan.
Mengimplementasikan callback daur hidup
Seperti aktivitas, layanan memiliki metode callback siklus proses yang dapat Anda terapkan untuk memantau mengubah status layanan dan melakukan pekerjaan pada waktu yang tepat. Kerangka berikut mendemonstrasikan setiap metode siklus proses:
Kotlin
class ExampleService : Service() { private var startMode: Int = 0 // indicates how to behave if the service is killed private var binder: IBinder? = null // interface for clients that bind private var allowRebind: Boolean = false // indicates whether onRebind should be used override funonCreate
() { // The service is being created } override funonStartCommand
(intent: Intent?, flags: Int, startId: Int): Int { // The service is starting, due to a call to startService() return startMode } override funonBind
(intent: Intent): IBinder? { // A client is binding to the service with bindService() return binder } override funonUnbind
(intent: Intent): Boolean { // All clients have unbound with unbindService() return allowRebind } override funonRebind
(intent: Intent) { // A client is binding to the service with bindService(), // after onUnbind() has already been called } override funonDestroy
() { // The service is no longer used and is being destroyed } }
Java
public class ExampleService extends Service { int startMode; // indicates how to behave if the service is killed IBinder binder; // interface for clients that bind boolean allowRebind; // indicates whether onRebind should be used @Override public voidonCreate
() { // The service is being created } @Override public intonStartCommand
(Intent intent, int flags, int startId) { // The service is starting, due to a call tostartService()
return startMode; } @Override public IBinderonBind
(Intent intent) { // A client is binding to the service withbindService()
return binder; } @Override public booleanonUnbind
(Intent intent) { // All clients have unbound withunbindService()
return allowRebind; } @Override public voidonRebind
(Intent intent) { // A client is binding to the service withbindService()
, // after onUnbind() has already been called } @Override public voidonDestroy
() { // The service is no longer used and is being destroyed } }
Catatan: Tidak seperti metode callback siklus proses aktivitas, tidak perlu memanggil implementasi superclass metode callback ini.
Gambar 2 mengilustrasikan metode callback yang lazim bagi suatu layanan. Meskipun angka itu memisahkan
layanan yang dibuat oleh startService()
dari
dibuat oleh bindService()
, pertahankan
ingat bahwa layanan apa pun, tidak peduli bagaimana awalnya, mungkin memungkinkan klien untuk mengikatnya.
Layanan yang awalnya dimulai dengan onStartCommand()
(oleh klien yang memanggil startService()
)
masih dapat menerima panggilan ke onBind()
(saat klien menelepon
bindService()
).
Dengan mengimplementasikan metode ini, Anda bisa memantau dua loop tersarang (nested loop) dari metode siklus proses:
- Seluruh masa aktif layanan terjadi antara waktu
onCreate()
dipanggil dan waktuonDestroy()
ditampilkan. Seperti halnya aktivitas, layanan melakukan penyiapan awal dionCreate()
dan melepaskan semua resource yang tersisa dionDestroy()
. Sebagai contoh, layanan pemutaran musik dapat membuat thread tempat musik diputar dionCreate()
, lalu dapat menghentikan thread dionDestroy()
.Catatan:
onCreate()
dan metodeonDestroy()
dipanggil untuk semua layanan, baik kunci dibuat olehstartService()
ataubindService()
. - Masa aktif aktif layanan dimulai dengan panggilan ke
onStartCommand()
atauonBind()
. Setiap metode diberiIntent
yang diteruskan kestartService()
ataubindService()
.Jika layanan dimulai, masa aktif aktif akan berakhir pada waktu yang sama dengan masa aktif seluruh berakhir (layanan masih aktif bahkan setelah
onStartCommand()
ditampilkan). Jika layanan terikat, masa aktif aktif akan berakhir saatonUnbind()
ditampilkan.
Catatan: Meskipun layanan yang sudah dimulai dihentikan oleh panggilan ke
baik stopSelf()
maupun stopService()
, tidak ada callback masing-masing untuk
(tidak ada callback onStop()
). Kecuali jika layanan terikat ke klien,
sistem menghancurkannya saat layanan dihentikan—onDestroy()
adalah satu-satunya callback yang diterima.
Untuk mengetahui informasi selengkapnya tentang cara membuat layanan yang menyediakan binding, lihat dokumen Layanan Terikat.
yang menyertakan informasi selengkapnya tentang onRebind()
di bagian tentang Mengelola siklus proses
layanan terikat.