What Is System Service In Android N
Service
adalah sebuah komponen aplikasi yang bisa melakukan operasi yang berjalan lama di latar belakang dan tidak menyediakan antarmuka pengguna. Komponen aplikasi lain bisa memulai layanan dan komponen aplikasi tersebut akan terus berjalan di latar belakang walaupun pengguna beralih ke aplikasi lain. Selain itu, komponen bisa mengikat ke layanan untuk berinteraksi dengannya dan bahkan melakukan komunikasi antarproses (IPC). Misalnya, layanan mungkin menangani transaksi jaringan, memutar musik, melakukan file I/O, atau berinteraksi dengan penyedia materi dari latar belakang.
Inilah tiga tipe layanan yang berbeda:
- Latar depan
- Layanan latar depan melakukan beberapa operasi yang terlihat oleh pengguna. Misalnya, aplikasi audio akan menggunakan layanan latar depan untuk memutar runway sound. Layanan latar depan harus menampilkan Notifikasi. Layanan latar depan terus berjalan bahkan saat pengguna tidak berinteraksi dengan aplikasi.
- Latar belakang
- Layanan latar belakang melakukan operasi yang tidak terlihat secara langsung oleh pengguna. Misalnya, jika aplikasi menggunakan layanan untuk memadatkan penyimpanannya, aplikasi tersebut biasanya akan menjadi layanan latar belakang.
Catatan: Jika aplikasi Anda menargetkan API level 26 atau yang lebih tinggi, sistem akan mengenakan pembatasan pada layanan latar belakang yang berjalan saat aplikasi tersebut tidak berada di latar depan. Dalam sebagian besar kasus seperti ini, aplikasi Anda harus menggunakan tugas terjadwal.
- Terikat
- Sebuah layanan akan terikat bila komponen aplikasi mengikatkan kepadanya dengan memanggil
bindService()
. Layanan terikat menawarkan antarmuka klien-server yang memungkinkan komponen berinteraksi dengan layanan tersebut, mengirim permintaan, mendapatkan hasil dan bahkan melakukannya pada sejumlah proses dengan komunikasi antarproses (IPC). Layanan terikat hanya berjalan selama komponen aplikasi terikat padanya. Beberapa komponen bisa diikat ke layanan sekaligus, namun bila semuanya telah dilepas, layanan akan dimusnahkan.
Walaupun dokumentasi ini umumnya membahas layanan yang dimulai dan terikat secara terpisah, layanan Anda bisa bekerja dengan dua cara—layanan tersebut bisa dimulai (untuk berjalan terus-menerus) dan juga memungkinkan pengikatan. Ini hanyalah masalah apakah Anda mengimplementasikan beberapa metode callback: onStartCommand()
untuk memungkinkan komponen memulainya dan onBind()
untuk memungkinkan pengikatan.
Apakah layanan Anda sudah dimulai, terikat, atau keduanya, semua komponen aplikasi bisa menggunakan layanan (bahkan dari aplikasi terpisah), demikian pula semua komponen bisa menggunakan suatu aktivitas—dengan memulainya dengan Intent
. Akan tetapi, Anda bisa mendeklarasikan layanan sebagai privat pada file manifes, dan memblokir akses dari aplikasi lain. Hal ini dibahas selengkapnya di bagian tentang Mendeklarasikan layanan dalam manifes.
Perhatian: Layanan berjalan di thread utama proses yang menjadi host-nya layanan tidak membuat thread-nya sendiri dan tidak berjalan pada proses terpisah kecuali bila Anda tentukan demikian. Jika layanan Anda akan melakukan pekerjaan yang banyak membutuhkan CPU atau operasi pemblokiran, seperti pemutaran MP3 atau jaringan, Anda harus membuat thread baru dalam layanan untuk menyelesaikan pekerjaan itu. Dengan menggunakan thread terpisah, Anda akan mengurangi risiko kesalahan Aplikasi Tidak Merespons (Application Not Responding/ANR) dan thread utama aplikasi bisa terus disediakan untuk interaksi pengguna dengan aktivitas Anda.
Memilih antara layanan dan thread
Layanan sekadar komponen yang bisa berjalan di latar belakang, walaupun pengguna sedang tidak berinteraksi dengan aplikasi Anda, sehingga Anda harus membuat layanan hanya jika itu yang diperlukan.
Jika Anda harus melakukan pekerjaan di luar thread utama, namun hanya saat pengguna berinteraksi dengan aplikasi Anda, Anda harus membuat thread baru. Misalnya, bila Anda ingin memutar musik, namun hanya saat aktivitas berjalan, Anda bisa membuat thread dalam onCreate()
, mulai menjalankannya di onStart()
, kemudian menghentikannya di onStop()
. Pertimbangkan juga untuk menggunakan AsyncTask
atau HandlerThread
, sebagai ganti class Thread
yang lazim digunakan. Lihat dokumen Proses dan Threading untuk informasi selengkapnya tentang thread.
Ingatlah jika menggunakan layanan, layanan tersebut tetap berjalan di thread utama aplikasi Anda secara default, jadi Anda harus tetap membuat thread baru dalam layanan bila layanan tersebut melakukan operasi yang intensif atau operasi yang memblokir.
Dasar-dasar
Untuk membuat layanan, Anda harus membuat bracket Service
atau salah satu dari subclass-nya yang ada. Dalam implementasi, Anda perlu mengganti sebagian metode callback yang menangani aspek utama daur hidup layanan dan memberikan mekanisme bagi komponen untuk mengikat pada layanan, bila dibutuhkan. Inilah metode callback paling penting yang harus Anda ganti:
-
onStartCommand()
- Sistem akan memicu metode ini dengan memanggil
startService()
bila komponen lain (seperti suatu aktivitas) meminta agar layanan dimulai. Jika metode ini dieksekusi, layanan akan dimulai dan bisa berjalan di latar belakang terus-menerus. Jika mengimplementasikannya, Anda bertanggung jawab menghentikan layanan setelah pekerjaannya selesai, dengan memanggilstopSelf()
ataustopService()
. Jika hanya ingin menyediakan pengikatan, Anda tidak perlu mengimplementasikan metode ini. -
onBind()
- Sistem akan memicu metode ini dengan memanggil
bindService()
bila komponen lain ingin mengikat pada layanan (misalnya untuk melakukan RPC). Dalam mengimplementasikan metode ini, Anda harus menyediakan antarmuka yang digunakan klien untuk berkomunikasi dengan layanan, dengan mengembalikanIBinder
. Anda harus selalu mengimplementasikan metode ini, namun jika tidak ingin mengizinkan pengikatan, Anda perlu mengembalikan null. -
onCreate()
- Sistem akan memicu metode untuk melakukan prosedur penyiapan satu kali saat layanan ini awalnya dibuat (sebelum memanggil
onStartCommand()
atauonBind()
). Bila layanan sudah berjalan, metode ini tidak dipanggil. -
onDestroy()
- Sistem akan memicu metode ini bila layanan tidak lagi digunakan dan sedang dihancurkan. Layanan Anda harus mengimplementasikan ini untuk membersihkan semua resource, seperti thread, listener terdaftar, atau penerima. Ini adalah panggilan terakhir yang diterima layanan.
Jika komponen memulai layanan dengan memanggil startService()
(yang menyebabkan panggilan ke onStartCommand()
, maka layanan akan terus berjalan hingga terhenti sendiri dengan stopSelf()
atau bila komponen lain menghentikannya dengan memanggil stopService()
.
Jika komponen memanggil bindService()
untuk membuat layanan dan onStartCommand()
tidak dipanggil, maka layanan hanya akan berjalan selama komponen terikat kepadanya. Setelah layanan dilepas ikatannya dari semua klien, sistem akan menghapusnya.
Sistem Android akan menghentikan layanan hanya bila memori tinggal sedikit dan sistem harus memulihkan resource sistem untuk aktivitas yang mendapatkan fokus pengguna. Jika layanan terikat pada aktivitas yang memiliki fokus pengguna, lebih kecil kemungkinan untuk dimatikan; jika layanan dideklarasikan untuk berjalan di latar depan, layanan itu jarang dimatikan. Jika layanan dimulai dan berjalan lama, sistem menurunkan posisinya dalam daftar tugas latar belakang seiring waktu, dan layanan ini menjadi sangat rentan dimatikan—jika layanan Anda dimulai, Anda harus mendesainnya agar dapat menangani mulai ulang oleh sistem dengan baik. Jika sistem mematikan layanan Anda, layanan akan dimulai ulang begitu resource kembali tersedia, tetapi ini juga bergantung pada nilai yang Anda kembalikan dari onStartCommand()
. Untuk informasi selengkapnya tentang kapan sistem mungkin akan memusnahkan layanan, lihat dokumen Proses dan Threading.
Di bagian berikut, Anda akan melihat cara membuat metode layanan startService()
dan bindService()
, serta cara menggunakannya dari komponen aplikasi lainnya.
Mendeklarasikan layanan dalam manifes
Anda harus mendeklarasikan semua layanan dalam file manifes aplikasi Anda, persis seperti yang Anda lakukan untuk aktivitas dan komponen lainnya.
Untuk mendeklarasikan layanan Anda, tambahkan sebuah elemen <service>
sebagai anak elemen <awarding>
. Berikut contohnya:
<manifest ... > ... <application ... > <service android:name=".ExampleService" /> ... </application> </manifest>
Lihat referensi elemen <service>
untuk informasi selengkapnya tentang mendeklarasikan layanan Anda dalam manifes.
Ada atribut lain yang bisa Anda sertakan dalam elemen <service>
untuk mendefinisikan properti seperti izin yang diperlukan untuk memulai layanan dan proses tempat menjalankannya. Atribut android:name
adalah satu-satunya yang diperlukan—atribut ini menetapkan nama class layanan. Setelah Anda menerbitkan aplikasi, biarkan nama ini tidak diubah untuk menghindari risiko merusak kode karena dependensi terhadap intent eksplisit untuk memulai atau mengikat layanan (bacalah entri weblog berjudul Things That Cannot Change).
Perhatian: Untuk memastikan aplikasi Anda aman, selalu gunakan intent eksplisit saat memulai Service
dan jangan mendeklarasikan filter intent untuk layanan. Menggunakan intent implisit untuk memulai layanan akan menimbulkan bahaya keamanan karena Anda tidak bisa memastikan layanan apa yang akan merespons intent, dan pengguna tidak bisa melihat layanan mana yang dimulai. Mulai dari Android 5.0 (API level 21), sistem melontarkan pengecualian jika Anda memanggil bindService()
dengan intent implisit.
Anda juga bisa memastikan layanan tersedia hanya bagi aplikasi dengan menyertakan atribut android:exported
dan menyetelnya ke false
. Cara ini efektif menghentikan aplikasi lain agar tidak memulai layanan Anda, bahkan saat menggunakan intent eksplisit.
Catatan: Pengguna bisa melihat layanan yang sedang berjalan di perangkat mereka. Jika mereka melihat layanan yang tidak dikenali atau dipercaya, mereka akan menghentikan layanan itu. Agar layanan Anda tidak dihentikan secara tidak sengaja oleh pengguna, Anda perlu menambahkan atribut android:description
ke elemen <service>
dalam manifes aplikasi Anda. Dalam keterangan, tuliskan kalimat singkat yang menjelaskan hal yang dilakukan layanan dan manfaat yang diberikan.
Membuat layanan yang sudah dimulai
Layanan yang sudah dimulai adalah layanan yang dimulai komponen lain dengan memanggil startService()
, yang menyebabkan panggilan ke metode onStartCommand()
layanan.
Saat layanan dimulai, layanan tersebut memiliki daur hidup yang independen dari komponen yang memulainya. Layanan bisa berjalan di latar belakang tanpa dibatasi waktu, sekalipun komponen yang memulainya telah dimusnahkan. Dengan sendirinya, layanan akan berhenti sendiri bila tugasnya selesai dengan memanggil stopSelf()
, atau komponen lain bisa menghentikannya dengan memanggil stopService()
.
Komponen aplikasi seperti aktivitas bisa memulai layanan dengan memanggil startService()
serta meneruskan Intent
yang menetapkan layanan dan menyertakan data yang akan digunakan layanan. Layanan menerima Intent
ini dalam metode onStartCommand()
.
Sebagai contoh, anggaplah aktivitas perlu menyimpan data ke database online. Aktivitas tersebut bisa memulai layanan pendamping dan mengiriminya data untuk disimpan dengan meneruskan intent ke startService()
. Layanan akan menerima intent dalam onStartCommand()
, menghubungkan ke Internet, dan melakukan transaksi database. Bila transaksi selesai, layanan akan berhenti sendiri dan dimusnahkan.
Perhatian: Layanan berjalan dalam proses yang sama dengan aplikasi tempatnya dideklarasikan dan dalam thread utama aplikasi tersebut, secara default. Jadi, bila layanan Anda melakukan operasi yang intensif atau operasi pemblokiran saat pengguna berinteraksi dengan aktivitas dari aplikasi yang sama, layanan akan memperlambat kinerja aktivitas. Agar tidak memengaruhi kinerja aplikasi, Anda harus memulai thread baru di dalam layanan.
Biasanya, ada dua class yang bisa Anda perluas untuk membuat layanan yang sudah dimulai:
-
Service
- Ini adalah class dasar untuk semua layanan. Saat memperluas class ini, Anda perlu membuat thread baru tempat layanan bisa menyelesaikan semua pekerjaannya; layanan ini menggunakan thread utama aplikasi Anda secara default, yang akan memperlambat kinerja semua aktivitas yang sedang dijalankan aplikasi Anda.
-
IntentService
- Ini adalah subclass
Service
yang menggunakan thread pekerja untuk menangani semua permintaan memulai, satu per satu. Ini adalah pilihan terbaik jika Anda tidak mengharuskan layanan menangani beberapa permintaan sekaligus. ImplementasikanonHandleIntent()
, yang akan menerima intent untuk setiap permintaan memulai sehingga Anda bisa menyelesaikan pekerjaan latar belakang.
Bagian selanjutnya membahas cara mengimplementasikan layanan Anda menggunakan salah satu dari class ini.
Memperluas class IntentService
Mengingat kebanyakan layanan yang sudah dimulai tidak perlu menangani beberapa permintaan sekaligus (yang bisa berupa skenario multi-threading berbahaya), mungkin Anda sebaiknya mengimplementasikan layanan menggunakan class IntentService
.
Class IntentService
melakukan hal berikut:
- Membuat thread pekerja default yang menjalankan semua intent yang disampaikan ke
onStartCommand()
terpisah dari thread utama aplikasi Anda. - Membuat antrean pekerjaan yang meneruskan intent satu per satu ke implementasi
onHandleIntent()
, sehingga Anda tidak perlu mengkhawatirkan multi-threading. - Menghentikan layanan setelah semua permintaan memulai telah ditangani, jadi Anda tidak perlu memanggil
stopSelf()
. - Menyediakan implementasi default
onBind()
yang mengembalikan aught. - Menyediakan implementasi default
onStartCommand()
yang mengirimkan intent ke antrean pekerjaan kemudian ke implementasionHandleIntent()
Anda.
Untuk menyelesaikan pekerjaan yang diberikan oleh klien, impelementasikan onHandleIntent()
. Akan tetapi, Anda juga perlu menyediakan konstruktor kecil bagi layanan.
Berikut ini contoh implementasi IntentService
:
Kotlin
/** * A constructor is required, and must telephone call the super [android.app.IntentService.IntentService] * constructor with a name for the worker thread. */ class HelloIntentService : IntentService("HelloIntentService") { /** * The IntentService calls this method from the default worker thread with * the intent that started the service. When this method returns, IntentService * stops the service, as advisable. */ override fun onHandleIntent(intent: Intent?) { // Normally nosotros would do some work here, like download a file. // For our sample, we but sleep for 5 seconds. try { Thread.slumber(5000) } catch (e: InterruptedException) { // Restore interrupt condition. Thread.currentThread().interrupt() } } }
Java
public class HelloIntentService extends IntentService { /** * A constructor is required, and must telephone call the super <code><a href="/reference/android/app/IntentService.html#IntentService(java.lang.String)">IntentService(String)</a></code> * constructor with a proper name for the worker thread. */ public HelloIntentService() { super("HelloIntentService"); } /** * The IntentService calls this method from the default worker thread with * the intent that started the service. When this method returns, IntentService * stops the service, as appropriate. */ @Override protected void onHandleIntent(Intent intent) { // Normally we would do some work here, like download a file. // For our sample, we just sleep for v seconds. try { Thread.slumber(5000); } catch (InterruptedException e) { // Restore interrupt condition. Thread.currentThread().interrupt(); } } }
Anda hanya memerlukan: konstruktor dan implementasi onHandleIntent()
.
Jika Anda memutuskan untuk menggantikan juga metode callback lain, seperti onCreate()
, onStartCommand()
, atau onDestroy()
, pastikan memanggil implementasi super sehingga IntentService
bisa menangani hidup thread pekerja dengan baik.
Misalnya, onStartCommand()
harus mengembalikan implementasi default, yang merupakan cara penyampaian intent ke onHandleIntent()
:
Kotlin
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show() return super.onStartCommand(intent, flags, startId) }
Java
@Override public int onStartCommand(Intent intent, int flags, int startId) { Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show(); return super.onStartCommand(intent,flags,startId); }
Selain onHandleIntent()
, satu-satunya metode yang bisa Anda lakukan tanpa memanggil superkelas adalah onBind()
. Anda perlu mengimplementasikan metode ini jika layanan Anda mengizinkan pengikatan.
Dalam bagian berikutnya, Anda akan melihat bagaimana layanan serupa diimplementasikan saat memperluas class Service
footing, yang membutuhkan kode lebih banyak lagi, namun mungkin cocok jika Anda perlu menangani beberapa permintaan memulai sekaligus.
Memperluas course Layanan
Menggunakan IntentService
membuat implementasi layanan yang sudah dimulai jadi sangat mudah. Namun, bila Anda mengharuskan layanan untuk melakukan multi-threading (sebagai ganti memproses permintaan memulai melalui antrean pekerjaan), maka Anda bisa memperluas class Service
untuk menangani masing-masing intent.
Sebagai perbandingan, kode contoh berikut ini adalah implementasi class Service
yang melakukan pekerjaan yang persis sama dengan contoh di atas dengan menggunakan IntentService
. Artinya, untuk setiap permintaan memulai, kode tersebut akan menggunakan thread pekerja untuk melakukan tugas dan memproses permintaan satu per satu.
Kotlin
class HelloService : Service() { private var serviceLooper: Looper? = zip 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 practice some work here, like download a file. // For our sample, we only sleep for 5 seconds. try { Thread.sleep(5000) } catch (due east: 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 treatment some other chore stopSelf(msg.arg1) } } override fun onCreate() { // First upwards the thread running the service. Annotation that nosotros create a // carve up thread because the service normally runs in the process's // master thread, which we don't desire to block. We also make information technology // background priority so CPU-intensive work volition not disrupt our UI. HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND).apply { starting time() // Get the HandlerThread's Looper and use information technology 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, ship a message to start a job and deliver the // start ID then we know which request we're stopping when we terminate the job serviceHandler?.obtainMessage()?.as well { 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 naught render aught } override fun onDestroy() { Toast.makeText(this, "service done", Toast.LENGTH_SHORT).bear witness() } }
Coffee
public class HelloService extends Service { private Looper serviceLooper; private ServiceHandler serviceHandler; // Handler that receives messages from the thread private final form ServiceHandler extends Handler { public ServiceHandler(Looper looper) { super(looper); } @Override public void handleMessage(Bulletin msg) { // Ordinarily we would do some work here, similar download a file. // For our sample, we but sleep for 5 seconds. try { Thread.sleep(5000); } grab (InterruptedException e) { // Restore interrupt condition. Thread.currentThread().interrupt(); } // Finish the service using the startId, so that nosotros 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 procedure's // main thread, which we don't want to cake. We also make it // groundwork priority and then CPU-intensive work doesn't disrupt our UI. HandlerThread thread = new HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND); thread.start(); // Go the HandlerThread'due south 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 outset asking, ship a message to outset a chore 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 nosotros go killed, after returning from here, restart return START_STICKY; } @Override public IBinder onBind(Intent intent) { // We don't provide bounden, so return null return null; } @Override public void onDestroy() { Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show(); } }
Seperti yang bisa Anda lihat, ini membutuhkan lebih banyak pekerjaan daripada menggunakan IntentService
.
Akan tetapi, karena Anda menangani sendiri setiap panggilan ke onStartCommand()
, Anda bisa melakukan beberapa permintaan sekaligus. Itu bukan yang dilakukan contoh ini, namun jika itu yang diinginkan, Anda bisa membuat thread baru untuk setiap permintaan dan langsung menjalankannya dan tidak menunggu permintaan sebelumnya selesai.
Perhatikan bahwa metode onStartCommand()
harus mengembalikan integer. Integer tersebut merupakan nilai yang menjelaskan cara sistem melanjutkan layanan dalam kejadian yang dimatikan oleh sistem. Implementasi default untuk IntentService
akan menangani integer, namun Anda bisa memodifikasinya. Nilai yang dikembalikan dari onStartCommand()
harus berupa salah satu konstanta berikut ini:
-
START_NOT_STICKY
- Jika sistem mematikan layanan setelah
onStartCommand()
dikembalikan, jangan membuat lagi layanan tersebut, kecuali jika ada intent tertunda yang akan disampaikan. Inilah pilihan teraman untuk menghindari menjalankan layanan Anda bila tidak diperlukan dan bila aplikasi Anda bisa memulai ulang tugas yang belum selesai. -
START_STICKY
- Jika sistem mematikan layanan setelah
onStartCommand()
kembali, buat kembali layanan dan panggilonStartCommand()
, namun jangan menyampaikan ulang intent terakhir. Sebagai gantinya, sistem memanggilonStartCommand()
dengan intent null kecuali ada intent tertunda yang akan memulai layanan. Dalam hal itu, intent tersebut disampaikan. Ini cocok bagi pemutar media (atau layanan serupa) yang tidak mengeksekusi perintah, namun berjalan terus-menerus dan menunggu tugas. -
START_REDELIVER_INTENT
- Jika sistem mematikan layanan setelah
onStartCommand()
kembali, buat kembali layanan dan panggilonStartCommand()
dengan intent terakhir yang disampaikan ke layanan. Intent yang tertunda akan disampaikan pada gilirannya. Ini cocok bagi layanan yang aktif melakukan tugas yang harus segera dilanjutkan, misalnya mendownload file.
Untuk detail selengkapnya tentang nilai pengembalian ini, lihat dokumentasi acuan tertaut untuk setiap konstanta. Untuk contoh tambahan dari tipe implementasi layanan, lihat course MessagingService
di Contoh MessagingService di GitHub.
Memulai layanan
Anda bisa memulai layanan dari aktivitas atau komponen aplikasi lain dengan meneruskan Intent
ke startService()
atau startForegroundService()
. Sistem Android akan memanggil metode onStartCommand()
layanan dan meneruskan Intent
padanya, yang menentukan layanan yang akan dimulai.
Catatan: Jika aplikasi Anda menargetkan API level 26 atau yang lebih tinggi, sistem akan mengenakan pembatasan pada layanan latar belakang yang berjalan saat aplikasi tersebut tidak berada di latar depan. Jika aplikasi perlu membuat layanan latar depan, aplikasi tersebut harus memanggil startForegroundService()
. Metode tersebut membuat layanan latar belakang, namun metode ini mengisyaratkan ke sistem bahwa layanan akan mempromosikan dirinya sendiri ke latar depan. Setelah layanan dibuat, layanan tersebut harus memanggil metode startForeground()
dalam lima detik.
Misalnya, aktivitas bisa memulai layanan contoh di bagian sebelumnya (HelloService
) menggunakan intent eksplisit dengan startService()
, seperti yang ditampilkan berikut:
Kotlin
Intent(this, HelloService::form.java).also { intent -> startService(intent) }
Java
Intent intent = new Intent(this, HelloService.class); startService(intent);
Metode startService()
segera kembali dan sistem Android akan memanggil metode onStartCommand()
layanan. Jika layanan tidak berjalan, sistem akan memanggil onCreate()
terlebih dahulu, kemudian memanggil onStartCommand()
.
Jika layanan juga tidak menyediakan pengikatan, intent yang disampaikan dengan startService()
adalah satu-satunya mode komunikasi antara komponen aplikasi dan layanan. Akan tetapi, jika Anda ingin agar layanan mengirimkan hasilnya kembali, maka klien yang memulai layanan bisa membuat PendingIntent
untuk siaran (dengan getBroadcast()
) dan menyampaikannya ke layanan dalam Intent
yang memulai layanan. Layanan kemudian bisa menggunakan siaran untuk menyampaikan hasil.
Beberapa permintaan untuk memulai layanan menghasilkan beberapa panggilan ke onStartCommand()
layanan. Akan tetapi, hanya satu permintaan untuk menghentikan layanan (dengan stopSelf()
atau stopService()
) yang diperlukan untuk menghentikannya.
Menghentikan layanan
Layanan yang sudah dimulai harus mengelola daur hidupnya sendiri. Artinya, sistem tidak menghentikan atau memusnahkan layanan kecuali jika harus memulihkan memori sistem dan layanan terus berjalan setelah onStartCommand()
kembali. Layanan tersebut harus berhenti sendiri dengan memanggil stopSelf()
atau komponen lain bisa menghentikannya dengan memanggil stopService()
.
Setelah diminta untuk berhenti dengan stopSelf()
atau stopService()
, sistem akan memusnahkan layanan secepatnya.
Bila layanan Anda menangani beberapa permintaan ke onStartCommand()
sekaligus, Anda tidak boleh menghentikan layanan bila baru selesai memproses permintaan memulai, karena setelah itu mungkin Anda sudah menerima permintaan memulai yang baru (berhenti pada permintaan pertama akan menghentikan permintaan kedua). Untuk menghindari masalah ini, Anda bisa menggunakan stopSelf(int)
untuk memastikan bahwa permintaan Anda untuk menghentikan layanan selalu berdasarkan pada permintaan memulai terbaru. Artinya, bila Anda memanggil stopSelf(int)
, Anda akan meneruskan ID permintaan memulai (startId
yang disampaikan ke onStartCommand()
) yang terkait dengan permintaan berhenti Anda. Kemudian, bila layanan menerima permintaan memulai yang baru sebelum Anda bisa memanggil stopSelf(int)
, ID tidak cocok dan layanan tidak berhenti.
Perhatian: Aplikasi Anda perlu menghentikan layanannya bila selesai bekerja untuk menghindari pemborosan resource sistem dan tenaga baterai. Jika perlu, komponen lain bisa menghentikan layanan dengan memanggil stopService()
. Bahkan jika Anda mengaktifkan pengikatan bagi layanan, Anda harus selalu menghentikan layanan sendiri jika layanan tersebut menerima panggilan ke onStartCommand()
.
Untuk informasi selengkapnya tentang daur hidup layanan, lihat bagian di bawah ini tentang Mengelola Daur Hidup Layanan.
Membuat layanan terikat
Layanan terikat adalah layanan yang memungkinkan komponen aplikasi untuk mengikatnya dengan memanggil bindService()
guna membuat koneksi yang berlangsung lama. Layanan ini tidak mengizinkan komponen memulainya dengan memanggil startService()
.
Buat layanan terikat bila ingin berinteraksi dengan layanan dari aktivitas dan komponen lain dalam aplikasi Anda atau mengeskpos sebagian fungsionalitas aplikasi Anda ke aplikasi lain melalui komunikasi antarproses (IPC).
Untuk membuat layanan terikat, Anda harus mengimplementasikan metode callback onBind()
untuk mengembalikan IBinder
yang menetapkan antarmuka bagi komunikasi dengan layanan. Komponen aplikasi lain kemudian bisa memanggil bindService()
untuk mengambil antarmuka dan mulai memanggil metode pada layanan. Layanan hanya hidup untuk melayani komponen aplikasi yang terikat padanya, jadi bila tidak ada komponen yang terikat pada layanan, sistem akan memusnahkannya. Anda tidak perlu menghentikan layanan terikat dengan cara yang sama seperti yang Anda lakukan saat layanan dimulai melalui onStartCommand()
.
Untuk mengimplementasikan layanan terikat, tentukan antarmuka yang menetapkan cara klien bisa berkomunikasi dengan layanan. Antarmuka antara layanan dan klien ini harus berupa implementasi IBinder
dan yang harus dikembalikan layanan Anda dari metode callback onBind()
. Setelah menerima IBinder
, klien bisa mulai berinteraksi dengan layanan melalui antarmuka tersebut.
Beberapa klien bisa mengikat ke layanan sekaligus. Bila klien selesai berinteraksi dengan layanan, klien akan memanggil unbindService()
untuk melepas ikatan. Bila tidak ada klien yang terikat pada layanan, sistem akan menghapus layanan tersebut.
Ada sejumlah cara untuk mengimplementasikan layanan terikat, dan implementasi tersebut lebih rumit daripada layanan yang dimulai. Karena alasan ini, pembahasan layanan terikat muncul di dokumen terpisah tentang Layanan Terikat.
Mengirim notifikasi ke pengguna
Setelah berjalan, layanan bisa memberi tahu pengguna tentang suatu kejadian menggunakan Notifikasi Toast atau Notifikasi Bilah Condition.
Notifikasi toast adalah pesan yang muncul sebentar pada permukaan jendela saat ini sebelum menghilang. Notifikasi bilah status memberikan ikon di bilah status dengan pesan, yang bisa dipilih oleh pengguna untuk melakukan suatu aksi (misalnya memulai suatu aktivitas).
Biasanya, notifikasi bilah status adalah teknik terbaik bila ada pekerjaan latar belakang seperti download file selesai, dan pengguna kini bisa menggunakannya. Bila pengguna memilih notifikasi dari tampilan diperluas, notifikasi akan bisa memulai aktivitas (misalnya menampilkan file yang baru didownload).
Lihat panduan developer Notifikasi Toast atau Notifikasi Bilah Status untuk informasi selengkapnya.
Menjalankan layanan di latar depan
Layanan latar depan adalah layanan yang diketahui pengguna, jadi ini bukan layanan yang bakal dimatikan sistem bila memori tinggal sedikit. Layanan latar depan harus memberikan notifikasi untuk bilah condition, yang ditempatkan di bawah heading Sedang berlangsung. Ini berarti notifikasi tidak bisa ditutup kecuali layanan ini dihentikan atau dihapus dari latar depan.
Perhatian: Batasi penggunaan layanan latar depan aplikasi Anda.
Anda hanya harus menggunakan layanan latar depan bila aplikasi Anda perlu melakukan tugas yang bisa diketahui oleh pengguna sekalipun saat pengguna tidak berinteraksi dengan aplikasi secara langsung. Karena alasan ini, layanan latar depan harus menampilkan notifikasi bilah status dengan prioritas PRIORITY_LOW
atau lebih tinggi, yang membantu memastikan pengguna mengetahui hal yang dilakukan aplikasi Anda. Jika tindakannya cukup rendah sehingga Anda ingin menggunakan notifikasi prioritas minimum, Anda mungkin tidak boleh menggunakan layanan; sebagai gantinya, pertimbangkan untuk menggunakan tugas terjadwal.
Setiap aplikasi yang menjalankan layanan akan menempatkan pemuatan tambahan pada sistem, menghabiskan resource sistem. Jika aplikasi mencoba menyembunyikan layanannya dengan menggunakan notifikasi prioritas rendah, hal ini bisa mengganggu kinerja aplikasi yang berinteraksi secara aktif dengan pengguna. Karena alasan ini, jika aplikasi mencoba menjalankan layanan dengan notifikasi prioritas minimum, sistem akan memanggil perilaku aplikasi dalam bagian bawah panel samping notifikasi.
Misalnya, pemutar musik yang memutar musik dari suatu layanan harus disetel untuk berjalan di latar depan, karena pengguna mengetahui operasi tersebut secara eksplisit. Notifikasi di bilah status dapat menunjukkan lagu saat ini dan memungkinkan pengguna meluncurkan aktivitas untuk berinteraksi dengan pemutar musik. Demikian pula, aplikasi yang memungkinkan pengguna melacak saat mereka berolahraga lari akan membutuhkan layanan latar depan untuk melacak lokasi pengguna.
Untuk meminta agar layanan Anda berjalan di latar depan, panggil startForeground()
. Metode ini memerlukan dua parameter: sebuah integer yang mengidentifikasi notifikasi secara unik dan Notification
untuk bilah condition. Notifikasi tersebut harus memiliki prioritas PRIORITY_LOW
atau yang lebih tinggi. Berikut contohnya:
Kotlin
val pendingIntent: PendingIntent = Intent(this, ExampleActivity::class.java).let { notificationIntent -> PendingIntent.getActivity(this, 0, notificationIntent, 0) } val notification: Notification = Notification.Builder(this, CHANNEL_DEFAULT_IMPORTANCE) .setContentTitle(getText(R.string.notification_title)) .setContentText(getText(R.cord.notification_message)) .setSmallIcon(R.drawable.icon) .setContentIntent(pendingIntent) .setTicker(getText(R.cord.ticker_text)) .build() startForeground(ONGOING_NOTIFICATION_ID, notification)
Coffee
Intent notificationIntent = new Intent(this, ExampleActivity.grade); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); Notification notification = new Notification.Architect(this, CHANNEL_DEFAULT_IMPORTANCE) .setContentTitle(getText(R.string.notification_title)) .setContentText(getText(R.string.notification_message)) .setSmallIcon(R.drawable.icon) .setContentIntent(pendingIntent) .setTicker(getText(R.string.ticker_text)) .build(); startForeground(ONGOING_NOTIFICATION_ID, notification);
Perhatian: ID integer yang Anda berikan ke startForeground()
tidak boleh 0.
Untuk menghapus layanan dari latar depan, panggil stopForeground()
. Metode ini memerlukan boolean, yang menunjukkan apakah notifikasi bilah status juga akan dihapus. Metode ini tidak menghentikan layanan. Akan tetapi, jika Anda menghentikan layanan sewaktu masih berjalan di latar depan, maka notifikasi juga akan dihapus.
Untuk informasi selengkapnya tentang notifikasi, lihat Membuat Notifikasi Bilah Status.
Mengelola daur hidup layanan
Daur hidup layanan jauh lebih sederhana daripada daur hidup aktivitas. Akan tetapi, lebih penting lagi adalah memerhatikan dengan cermat bagaimana layanan Anda dibuat dan dimusnahkan, karena suatu layanan bisa berjalan di latar belakang tanpa disadari oleh pengguna.
Daur hidup layanan—dari saat dibuat hingga dimusnahkan—bisa mengikuti dua jalur berbeda:
- Layanan yang sudah dimulai
Layanan dibuat bila komponen lain memanggil
startService()
. Layanan kemudian berjalan terus-menerus dan harus berhenti sendiri dengan memanggilstopSelf()
. Komponen lain juga bisa menghentikan layanan dengan memanggilstopService()
. Bila layanan dihentikan, sistem akan memusnahkannya. - Layanan terikat
Layanan dibuat bila komponen lain (klien) memanggil
bindService()
. Klien kemudian berkomunikasi dengan layanan melalui antarmukaIBinder
. Klien bisa menutup koneksi dengan memanggilunbindService()
. Sejumlah klien bisa mengikat pada layanan yang sama dan bila semuanya melepas ikatan, sistem akan memusnahkan layanan tersebut. Layanan tidak perlu berhenti sendiri.
Kedua jalur ini tidak sepenuhnya terpisah. Artinya, Anda bisa mengikat ke layanan yang sudah dimulai dengan startService()
. Misalnya, Anda bisa memulai layanan musik latar belakang dengan memanggil startService()
dengan Intent
yang mengidentifikasi musik yang akan diputar. Kemudian, mungkin saat pengguna ingin mengontrol pemutar musik atau mendapatkan informasi tentang lagu saat ini, aktivitas bisa mengikat ke layanan dengan memanggil bindService()
. Bila seperti ini, stopService()
atau stopSelf()
tidak benar-benar menghentikan layanan hingga semua klien melepaskan ikatan.
Mengimplementasikan callback daur hidup
Seperti aktivitas, layanan memiliki metode callback daur hidup yang bisa Anda implementasikan untuk memantau perubahan keadaan layanan dan melakukan pekerjaan pada waktu yang sesuai. Layanan skeleton berikut memperagakan setiap metode daur hidup:
Kotlin
course ExampleService : Service() { individual var startMode: Int = 0 // indicates how to behave if the service is killed private var binder: IBinder? = null // interface for clients that demark private var allowRebind: Boolean = imitation // indicates whether onRebind should be used override funonCreate
() { // The service is existence created } override funonStartCommand
(intent: Intent?, flags: Int, startId: Int): Int { // The service is starting, due to a call to startService() return mStartMode } override funonBind
(intent: Intent): IBinder? { // A customer is bounden to the service with bindService() return mBinder } override funonUnbind
(intent: Intent): Boolean { // All clients accept unbound with unbindService() return mAllowRebind } 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 grade ExampleService extends Service { int startMode; // indicates how to comport if the service is killed IBinder binder; // interface for clients that demark boolean allowRebind; // indicates whether onRebind should be used @Override public voidonCreate
() { // The service is existence created } @Override public intonStartCommand
(Intent intent, int flags, int startId) { // The service is starting, due to a phone call tostartService()
return mStartMode; } @Override public IBinderonBind
(Intent intent) { // A client is binding to the service withbindService()
return mBinder; } @Override public booleanonUnbind
(Intent intent) { // All clients accept unbound withunbindService()
return mAllowRebind; } @Override public voidonRebind
(Intent intent) { // A client is binding to the service withbindService()
, // after onUnbind() has already been chosen } @Override public voidonDestroy
() { // The service is no longer used and is being destroyed } }
Catatan: Tidak seperti metode callback daur hidup aktivitas, Anda tidak perlu memanggil implementasi superclass metode callback tersebut.
Gambar 2. Daur hidup layanan. Diagram di sebelah kiri menampilkan daur hidup bila layanan dibuat dengan startService()
dan diagram di sebelah kanan menampilkan daur hidup bila layanan dibuat dengan bindService()
.
Gambar 2 mengilustrasikan metode callback yang lazim bagi suatu layanan. Walaupun gambar tersebut memisahkan layanan yang dibuat oleh startService()
dari layanan yang dibuat oleh bindService()
, ingatlah bahwa suatu layanan, bagaimana pun dimulainya, bisa memungkinkan klien mengikat padanya. Layanan yang awalnya dimulai dengan onStartCommand()
(dengan klien memanggil startService()
) bisa menerima panggilan ke onBind()
(bila klien memanggil bindService()
).
Dengan mengimplementasikan metode-metode ini, Anda bisa memantau dua loop tersarang (nested loop) daur hidup layanan:
- Seluruh masa pakai layanan terjadi antara waktu yang
onCreate()
dipanggil dan waktu yangonDestroy()
kembali. Seperti halnya aktivitas, layanan melakukan penyiapan awal dionCreate()
dan melepaskan semua sisa resources yang ada dionDestroy()
. Misalnya, layanan playback musik bisa membuat thread tempat musik diputar dalamonCreate()
, kemudian bisa menghentikan thread dalamonDestroy()
.Catatan: Metode
onCreate()
danonDestroy()
dipanggil untuk semua layanan, baik yang dibuat olehstartService()
maupunbindService()
. - Masa pakai aktif layanan dimulai dengan panggilan ke
onStartCommand()
atauonBind()
. Masing-masing metode diberikanIntent
yang diteruskan kestartService()
ataubindService()
.Jika layanan telah dimulai, masa pakai aktif akan berakhir pada saat yang sama dengan berakhirnya seluruh masa pakai (layanan masih aktif bahkan setelah
onStartCommand()
kembali). Jika layanan tersebut terikat, masa pakai aktifnya akan berakhir bilaonUnbind()
kembali.
Catatan: Meskipun layanan yang sudah dimulai dihentikan dengan panggilan ke stopSelf()
atau stopService()
, tidak ada callback tersendiri bagi layanan tersebut (tidak ada callback onStop()
). Kecuali jika layanan terikat ke klien, sistem akan memusnahkannya bila layanan dihentikan—onDestroy()
adalah satu-satunya callback yang diterima.
Untuk informasi selengkapnya tentang membuat layanan yang menyediakan pengikatan, lihat dokumen Layanan Terikat, yang menyertakan informasi selengkapnya tentang metode callback onRebind()
di bagian tentang Mengelola daur hidup layanan terikat.
What Is System Service In Android N,
Source: https://developer.android.com/guide/components/services?hl=id
Posted by: lyoncataing35.blogspot.com
0 Response to "What Is System Service In Android N"
Post a Comment