Layanan terikat adalah server di antarmuka klien-server. Layanan terikat memungkinkan komponen (seperti aktivitas) untuk diikat ke layanan, mengirim permintaan, menerima respons, dan melakukan komunikasi antarproses (IPC). Layanan terikat biasanya aktif hanya saat melayani komponen aplikasi lain dan tidak berjalan di latar belakang terus-menerus. Show Dokumen ini menjelaskan cara membuat layanan terikat, termasuk cara mengikat ke layanan dari komponen aplikasi lain. Untuk informasi tambahan tentang layanan secara umum, seperti cara menyampaikan notifikasi dari layanan dan mengatur layanan agar berjalan di latar depan, Anda dapat membaca dokumen Layanan. Dasar-dasarLayanan terikat adalah implementasi class Service yang memungkinkan aplikasi lain diikat padanya dan berinteraksi dengannya. Untuk menyediakan pengikatan bagi sebuah layanan, Anda harus mengimplementasikan metode callback onBind(). Metode ini menampilkan objek IBinder yang mendefinisikan antarmuka pemrograman yang dapat digunakan klien untuk berinteraksi dengan layanan. Mengikat ke layanan yang sudah dimulaiSeperti dibahas dalam dokumen Layanan, Anda dapat membuat layanan yang dimulai sekaligus diikat. Yakni, Anda dapat memulai layanan dengan memanggil startService(), yang memungkinkan layanan berjalan terus-menerus, dan juga memungkinkan klien mengikat ke layanan dengan memanggil bindService(). Jika Anda mengizinkan layanan dimulai dan diikat, lalu saat layanan telah dimulai, sistem tidak akan menghapus layanan ketika semua klien melepas ikatan. Sebaliknya, Anda harus menghentikan layanan secara eksplisit, dengan memanggil stopSelf() atau stopService(). Meskipun biasanya Anda harus mengimplementasikan onBind() atau onStartCommand(), terkadang perlu untuk mengimplementasikan keduanya. Misalnya, pemutar musik dapat merasakan manfaatnya karena layanan boleh berjalan terus-menerus dan juga menyediakan pengikatan. Dengan cara ini, suatu aktivitas dapat memulai layanan untuk memutar beberapa lagu dan musik agar terus dimainkan meskipun pengguna meninggalkan aplikasi. Lalu, saat pengguna kembali ke aplikasi, aktivitas dapat mengikat ke layanan untuk mendapatkan kembali kontrol pemutaran. Untuk informasi selengkapnya tentang siklus proses layanan saat menambahkan pengikatan ke layanan yang sudah dimulai, lihat Mengelola siklus proses Layanan terikat. Klien mengikat ke layanan dengan memanggil bindService(). Bila itu dilakukan, klien harus menyediakan implementasi ServiceConnection, yang akan memantau koneksi dengan layanan. Nilai hasil bindService() menunjukkan apakah layanan yang diminta ada dan apakah klien diziinkan mengaksesnya. Saat sistem Android membuat koneksi antara klien dan layanan, sistem tersebut memanggil onServiceConnected() pada ServiceConnection. Metode onServiceConnected() berisi argumen IBinder, yang kemudian digunakan klien untuk berkomunikasi dengan layanan terikat. Anda dapat menghubungkan beberapa klien ke layanan secara bersamaan. Namun, sistem melakukan cache pada saluran komunikasi layanan IBinder. Dengan kata lain, sistem memanggil metode onBind() layanan untuk membuat IBinder hanya saat klien pertama mengikat. Sistem kemudian memberikan IBinder yang sama ke semua klien tambahan yang mengikat ke layanan yang sama, tanpa memanggil onBind() lagi. Saat klien terakhir melepas ikatan dari layanan, sistem akan menghapus layanan, kecuali jika layanan juga dimulai oleh startService(). Bagian terpenting dari implementasi layanan terikat Anda adalah mendefinisikan antarmuka yang dikembalikan metode callback onBind() Anda. Bagian berikut membahas tentang berbagai cara untuk menentukan antarmuka IBinder layanan Anda. Membuat layanan terikatSaat membuat layanan yang menyediakan pengikatan, Anda harus menyediakan IBinder yang menyediakan antarmuka pemrograman yang dapat digunakan klien untuk berinteraksi dengan layanan. Ada tiga cara untuk menentukan antarmuka: Memperluas class Binder Jika layanan Anda bersifat privat untuk aplikasi Anda sendiri dan berjalan dalam proses yang sama dengan klien (biasanya), Anda harus membuat antarmuka dengan memperluas class Binder dan mengembalikan instance dari onBind(). Klien akan menerima Binder dan dapat menggunakannya untuk mengakses langsung metode publik yang tersedia dalam implementasi Binder atau Service.Inilah teknik yang lebih disukai bila layanan Anda sekadar pekerja latar belakang untuk aplikasi Anda sendiri. Satu-satunya alasan untuk tidak membuat antarmuka dengan cara ini adalah karena layanan Anda akan digunakan oleh aplikasi lain atau pada proses terpisah. Menggunakan Messenger Jika antarmuka Anda perlu bekerja lintas proses yang berbeda, Anda dapat membuat antarmuka untuk layanan dengan Messenger. Dengan cara ini, layanan mendefinisikan Handler yang akan merespons berbagai tipe objek Message. Handler ini adalah dasar bagi Messenger yang nantinya dapat berbagi IBinder dengan klien, sehingga memungkinkan klien mengirim perintah ke layanan dengan menggunakan objek Message. Selain itu, klien dapat mendefinisikan sendiri Messenger, sehingga layanan dapat mengirim balik pesan.Inilah cara termudah melakukan komunikasi antarproses (IPC), karena Messenger akan membuat antrean semua permintaan ke dalam satu thread, sehingga Anda tidak perlu mendesain layanan agar thread-safe. Untuk menggunakan AIDL secara langsung, Anda harus membuat file .aidl yang menetapkan antarmuka pemrograman. Android SDK Tools menggunakan file ini untuk menghasilkan class abstrak yang mengimplementasikan antarmuka dan menangani IPC, yang nantinya dapat Anda perluas dalam layanan. Catatan: Umumnya aplikasi tidak boleh menggunakan AIDL untuk membuat layanan terikat, karena hal itu mungkin memerlukan kemampuan multi-thread dan dapat mengakibatkan implementasi yang lebih rumit. Dengan demikian, AIDL tidak cocok untuk sebagian besar aplikasi dan dokumen ini tidak membahas cara menggunakannya untuk layanan Anda. Jika Anda yakin perlu menggunakan AIDL secara langsung, lihat dokumen AIDL. Memperluas class BinderJika layanan Anda hanya digunakan oleh aplikasi lokal dan tidak perlu bekerja lintas proses, maka Anda dapat mengimplementasikan class Binder Anda sendiri yang memberi klien Anda akses langsung ke metode publik dalam layanan. Catatan: Hal ini hanya berhasil jika klien dan layanan berada dalam aplikasi dan proses yang sama, suatu kondisi yang paling umum. Misalnya, cara ini sangat cocok untuk aplikasi musik yang perlu mengikat aktivitas ke layanannya sendiri, yakni memutar musik di latar belakang. Berikut cara menyiapkannya
Catatan: Layanan dan klien harus berada di aplikasi yang sama sehingga klien dapat mentransmisikan objek yang dikembalikan dan memanggil API-nya dengan benar. Layanan dan klien juga harus berada dalam proses yang sama, karena teknik ini tidak melakukan pengarahan (marshaling) apa pun lintas proses. Misalnya, berikut adalah layanan yang memberi klien akses ke metode dalam layanan melalui implementasi Binder:
LocalBinder menyediakan metode getService() bagi klien untuk mengambil instance LocalService saat ini. Cara ini memungkinkan klien memanggil metode publik dalam layanan. Misalnya, klien dapat memanggil getRandomNumber() dari layanan. Berikut adalah aktivitas yang mengikat ke LocalService dan memanggil getRandomNumber() bila tombol diklik:
Contoh di atas menampilkan cara klien mengikat ke layanan menggunakan implementasi ServiceConnection dan callback onServiceConnected(). Bagian berikut menyediakan informasi lebih lanjut tentang proses pengikatan ke layanan. Catatan: Dalam contoh di atas, metode onStop() akan melepas pengikatan klien dari layanan. Klien harus lepas dari layanan pada waktu yang tepat, seperti yang dibahas dalam Catatan tambahan. Untuk kode contoh selengkapnya, lihat class LocalService.java dan class LocalServiceActivities.java dalam ApiDemos. Menggunakan MessengerJika layanan perlu berkomunikasi dengan proses jauh, Anda dapat menggunakan Messenger untuk menyediakan antarmuka bagi layanan Anda. Teknik ini memungkinkan Anda melakukan komunikasi antarproses (IPC) tanpa harus menggunakan AIDL. Menggunakan Messenger untuk antarmuka Anda lebih mudah dibandingkan menggunakan AIDL karena Messenger membuat antrean semua panggilan ke layanan. Antarmuka AIDL murni mengirim permintaan secara bersamaan ke layanan, yang kemudian harus menangani multi-thread. Untuk sebagian besar aplikasi, layanan tidak perlu melakukan multi-thread, jadi menggunakan Messenger memungkinkan layanan menangani panggilan satu per satu. Jika layanan harus multi-thread, gunakan AIDL untuk menetapkan antarmuka. Berikut adalah ringkasan cara menggunakan Messenger: Dengan cara ini, tidak ada metode untuk dipanggil klien pada layanan. Sebagai gantinya, klien mengirim pesan (objek Message) yang diterima layanan dalam Handler-nya. Berikut adalah contoh layanan sederhana yang menggunakan antarmuka Messenger:
Perhatikan bahwa metode handleMessage() dalam Handler adalah tempat layanan menerima Message yang masuk dan memutuskan tindakan yang harus dilakukan, berdasarkan anggota what. Klien tinggal membuat Messenger berdasarkan IBinder yang dikembalikan oleh layanan dan mengirim pesan menggunakan send(). Misalnya, berikut adalah aktivitas sederhana yang mengikat ke layanan dan mengirim pesan MSG_SAY_HELLO ke layanan:
Perhatikan bahwa contoh ini tidak menampilkan cara layanan merespons klien. Jika ingin layanan merespons, Anda juga perlu membuat Messenger di klien. Saat klien menerima callback onServiceConnected(), klien akan mengirim Message ke layanan yang berisi Messenger klien dalam parameter replyTo metode send(). Anda dapat melihat contoh cara menyediakan fitur pesan dua arah dalam contoh MessengerService.java (layanan) dan MessengerServiceActivities.java (klien). Mengikat ke layananKomponen aplikasi (klien) dapat mengikat ke layanan dengan memanggil bindService(). Sistem Android kemudian memanggil onBind() layanan, yang mengembalikan IBinder untuk berinteraksi dengan layanan. Pengikatan tersebut asinkron, dan bindService() segera kembali tanpa mengembalikan IBinder ke klien. Untuk menerima IBinder, klien harus membuat instance ServiceConnection dan meneruskannya ke bindService(). ServiceConnection berisi metode callback yang dipanggil sistem untuk mengirim IBinder. Catatan: Hanya aktivitas, layanan, dan penyedia konten yang dapat mengikat ke layanan, yang tidak dapat Anda ikat ke layanan dari penerima siaran. Jadi, untuk mengikat layanan dari klien, Anda harus:
Contoh berikut menghubungkan klien ke layanan yang dibuat di atas dengan memperluas class Binder, sehingga tinggal mentransmisikan IBinder yang dikembalikan ke class LocalBinder dan meminta instance LocalService:
Dengan ServiceConnection ini, klien bisa mengikat ke layanan dengan meneruskannya ke bindService(), seperti yang ditampilkan pada contoh berikut:
Catatan tambahanBerikut ini beberapa catatan penting tentang pengikatan ke layanan:
Untuk kode contoh selengkapnya, yang menampilkan cara mengikat ke layanan, lihat class RemoteService.java dalam ApiDemos. Mengelola siklus proses layanan terikatBila layanan dilepas ikatannya dari semua klien, sistem Android akan menghapusnya (kecuali jika layanan juga dimulai dengan memanggil startService()). Dengan demikian, Anda tidak perlu mengelola siklus proses layanan jika layanan tersebut murni berupa layanan terikat. Sistem Android mengelolanya untuk Anda bergantung pada apakah layanan terikat ke klien atau tidak. Namun, jika Anda memilih untuk mengimplementasikan metode callback onStartCommand(), Anda harus menghentikan layanan secara eksplisit, karena layanan dianggap sudah dimulai. Dalam hal ini, layanan akan berjalan hingga menghentikan dirinya sendiri dengan stopSelf() atau komponen lain memanggil stopService(), terlepas dari apakah layanan terikat ke klien atau tidak. Selain itu, jika layanan dimulai dan menerima pengikatan, maka saat sistem memanggil metode onUnbind(), Anda dapat memilih untuk mengembalikan true jika ingin menerima panggilan ke onRebind() saat klien mengikat ke layanan. onRebind() tidak mengembalikan apa-apa, namun klien masih menerima IBinder dalam callback onServiceConnected(). Gambar di bawah ini mengilustrasikan logika untuk jenis siklus proses ini. Untuk informasi selengkapnya tentang siklus proses layanan yang telah dimulai, lihat dokumen Layanan. |