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.
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-dasar
Layanan 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 dimulai
Seperti 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 terikat
Saat 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 darionBind()
. Klien akan menerimaBinder
dan dapat menggunakannya untuk mengakses langsung metode publik yang tersedia dalam implementasiBinder
atauService
.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 mendefinisikanHandler
yang akan merespons berbagai tipe objekMessage
.Handler
ini adalah dasar bagiMessenger
yang nantinya dapat berbagiIBinder
dengan klien, sehingga memungkinkan klien mengirim perintah ke layanan dengan menggunakan objekMessage
. Selain itu, klien dapat mendefinisikan sendiriMessenger
, 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. - Menggunakan AIDL
- AIDL (Android Interface Definition Language) mengurai objek menjadi
primitif yang dapat dipahami sistem operasi, dan mengarahkan objek lintas proses untuk melakukan
IPC. Teknik sebelumnya, yang menggunakan
Messenger
, sebenarnya didasarkan pada AIDL yang menjadi struktur dasarnya. Seperti disebutkan di atas,Messenger
membuat antrean semua permintaan klien dalam satu thread, sehingga layanan akan menerima permintaan satu per satu. Namun, jika ingin layanan Anda menangani beberapa permintaan sekaligus, Anda dapat menggunakan AIDL secara langsung. Dalam hal ini, layanan Anda harus berupa thread-safe dan mampu melakukan multi-thread.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 Binder
Jika 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
- Dalam layanan Anda, buat sebuah instance
Binder
yang melakukan salah satu aktivitas berikut:- Menampung metode publik yang dapat dipanggil klien.
- Mengembalikan instance
Service
saat ini, yang memiliki metode publik yang dapat dipanggil klien. - Mengembalikan instance class lain yang di-host di layanan dengan metode publik yang dapat dipanggil klien.
- Mengembalikan instance
Binder
ini dari metode callbackonBind()
. - Di klien, terima
Binder
dari metode callbackonServiceConnected()
, lalu buat panggilan ke layanan terikat menggunakan metode yang disediakan.
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
:
Kotlin
class LocalService : Service() { // Binder given to clients private val binder = LocalBinder() // Random number generator private val mGenerator = Random() /** method for clients */ val randomNumber: Int get() = mGenerator.nextInt(100) /** * Class used for the client Binder. Because we know this service always * runs in the same process as its clients, we don't need to deal with IPC. */ inner class LocalBinder : Binder() { // Return this instance of LocalService so clients can call public methods fun getService(): LocalService = this@LocalService } override fun onBind(intent: Intent): IBinder { return binder } }
Java
public class LocalService extends Service { // Binder given to clients private final IBinder binder = new LocalBinder(); // Random number generator private final Random mGenerator = new Random(); /** * Class used for the client Binder. Because we know this service always * runs in the same process as its clients, we don't need to deal with IPC. */ public class LocalBinder extends Binder { LocalService getService() { // Return this instance of LocalService so clients can call public methods return LocalService.this; } } @Override public IBinder onBind(Intent intent) { return binder; } /** method for clients */ public int getRandomNumber() { return mGenerator.nextInt(100); } }
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:
Kotlin
class BindingActivity : Activity() { private lateinit var mService: LocalService private var mBound: Boolean = false /** Defines callbacks for service binding, passed to bindService() */ private val connection = object : ServiceConnection { override fun onServiceConnected(className: ComponentName, service: IBinder) { // We've bound to LocalService, cast the IBinder and get LocalService instance val binder = service as LocalService.LocalBinder mService = binder.getService() mBound = true } override fun onServiceDisconnected(arg0: ComponentName) { mBound = false } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.main) } override fun onStart() { super.onStart() // Bind to LocalService Intent(this, LocalService::class.java).also { intent -> bindService(intent, connection, Context.BIND_AUTO_CREATE) } } override fun onStop() { super.onStop() unbindService(connection) mBound = false } /** Called when a button is clicked (the button in the layout file attaches to * this method with the android:onClick attribute) */ fun onButtonClick(v: View) { if (mBound) { // Call a method from the LocalService. // However, if this call were something that might hang, then this request should // occur in a separate thread to avoid slowing down the activity performance. val num: Int = mService.randomNumber Toast.makeText(this, "number: $num", Toast.LENGTH_SHORT).show() } } }
Java
public class BindingActivity extends Activity { LocalService mService; boolean mBound = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } @Override protected void onStart() { super.onStart(); // Bind to LocalService Intent intent = new Intent(this, LocalService.class); bindService(intent, connection, Context.BIND_AUTO_CREATE); } @Override protected void onStop() { super.onStop(); unbindService(connection); mBound = false; } /** Called when a button is clicked (the button in the layout file attaches to * this method with the android:onClick attribute) */ public void onButtonClick(View v) { if (mBound) { // Call a method from the LocalService. // However, if this call were something that might hang, then this request should // occur in a separate thread to avoid slowing down the activity performance. int num = mService.getRandomNumber(); Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show(); } } /** Defines callbacks for service binding, passed to bindService() */ private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { // We've bound to LocalService, cast the IBinder and get LocalService instance LocalBinder binder = (LocalBinder) service; mService = binder.getService(); mBound = true; } @Override public void onServiceDisconnected(ComponentName arg0) { mBound = false; } }; }
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 Messenger
Jika 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
:
- Layanan mengimplementasikan
Handler
yang menerima callback untuk setiap panggilan dari klien. - Layanan menggunakan
Handler
untuk membuat objekMessenger
(yang merupakan acuan keHandler
). Messenger
membuatIBinder
yang dikembalikan layanan ke klien darionBind()
.- Klien menggunakan
IBinder
untuk membuat instanceMessenger
(yang mengacuHandler
layanan), yang digunakan klien untuk mengirim objekMessage
ke layanan. - Layanan menerima setiap
Message
dalamHandler
secara spesifik, dalam metodehandleMessage()
.
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
:
Kotlin
/** Command to the service to display a message */ private const val MSG_SAY_HELLO = 1 class MessengerService : Service() { /** * Target we publish for clients to send messages to IncomingHandler. */ private lateinit var mMessenger: Messenger /** * Handler of incoming messages from clients. */ internal class IncomingHandler( context: Context, private val applicationContext: Context = context.applicationContext ) : Handler() { override fun handleMessage(msg: Message) { when (msg.what) { MSG_SAY_HELLO -> Toast.makeText(applicationContext, "hello!", Toast.LENGTH_SHORT).show() else -> super.handleMessage(msg) } } } /** * When binding to the service, we return an interface to our messenger * for sending messages to the service. */ override fun onBind(intent: Intent): IBinder? { Toast.makeText(applicationContext, "binding", Toast.LENGTH_SHORT).show() mMessenger = Messenger(IncomingHandler(this)) return mMessenger.binder } }
Java
public class MessengerService extends Service { /** * Command to the service to display a message */ static final int MSG_SAY_HELLO = 1; /** * Handler of incoming messages from clients. */ static class IncomingHandler extends Handler { private Context applicationContext; IncomingHandler(Context context) { applicationContext = context.getApplicationContext(); } @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_SAY_HELLO: Toast.makeText(applicationContext, "hello!", Toast.LENGTH_SHORT).show(); break; default: super.handleMessage(msg); } } } /** * Target we publish for clients to send messages to IncomingHandler. */ Messenger mMessenger; /** * When binding to the service, we return an interface to our messenger * for sending messages to the service. */ @Override public IBinder onBind(Intent intent) { Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show(); mMessenger = new Messenger(new IncomingHandler(this)); return mMessenger.getBinder(); } }
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:
Kotlin
class ActivityMessenger : Activity() { /** Messenger for communicating with the service. */ private var mService: Messenger? = null /** Flag indicating whether we have called bind on the service. */ private var bound: Boolean = false /** * Class for interacting with the main interface of the service. */ private val mConnection = object : ServiceConnection { override fun onServiceConnected(className: ComponentName, service: IBinder) { // This is called when the connection with the service has been // established, giving us the object we can use to // interact with the service. We are communicating with the // service using a Messenger, so here we get a client-side // representation of that from the raw IBinder object. mService = Messenger(service) bound = true } override fun onServiceDisconnected(className: ComponentName) { // This is called when the connection with the service has been // unexpectedly disconnected -- that is, its process crashed. mService = null bound = false } } fun sayHello(v: View) { if (!bound) return // Create and send a message to the service, using a supported 'what' value val msg: Message = Message.obtain(null, MSG_SAY_HELLO, 0, 0) try { mService?.send(msg) } catch (e: RemoteException) { e.printStackTrace() } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.main) } override fun onStart() { super.onStart() // Bind to the service Intent(this, MessengerService::class.java).also { intent -> bindService(intent, mConnection, Context.BIND_AUTO_CREATE) } } override fun onStop() { super.onStop() // Unbind from the service if (bound) { unbindService(mConnection) bound = false } } }
Java
public class ActivityMessenger extends Activity { /** Messenger for communicating with the service. */ Messenger mService = null; /** Flag indicating whether we have called bind on the service. */ boolean bound; /** * Class for interacting with the main interface of the service. */ private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { // This is called when the connection with the service has been // established, giving us the object we can use to // interact with the service. We are communicating with the // service using a Messenger, so here we get a client-side // representation of that from the raw IBinder object. mService = new Messenger(service); bound = true; } public void onServiceDisconnected(ComponentName className) { // This is called when the connection with the service has been // unexpectedly disconnected -- that is, its process crashed. mService = null; bound = false; } }; public void sayHello(View v) { if (!bound) return; // Create and send a message to the service, using a supported 'what' value Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0); try { mService.send(msg); } catch (RemoteException e) { e.printStackTrace(); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } @Override protected void onStart() { super.onStart(); // Bind to the service bindService(new Intent(this, MessengerService.class), mConnection, Context.BIND_AUTO_CREATE); } @Override protected void onStop() { super.onStop(); // Unbind from the service if (bound) { unbindService(mConnection); bound = false; } } }
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 layanan
Komponen 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:
- Mengimplementasikan
ServiceConnection
.Implementasi Anda harus mengganti dua metode callback:
onServiceConnected()
- Sistem memanggil ini untuk mengirim
IBinder
yang dikembalikan oleh metodeonBind()
layanan. onServiceDisconnected()
- Sistem Android memanggil ini bila koneksi ke layanan putus tanpa terduga, seperti ketika layanan bermasalah atau dimatikan. Ini tidak dipanggil saat klien melepas ikatan.
- Panggil
bindService()
, dengan meneruskan implementasiServiceConnection
.Catatan: Jika metode ini mengembalikan false, berarti klien Anda tidak memiliki koneksi yang valid ke layanan. Namun, klien Anda tetap harus memanggil
unbindService()
; jika tidak, klien Anda akan menjaga agar layanan tidak dimatikan saat tidak ada aktivitas. - Bila sistem memanggil metode callback
onServiceConnected()
, Anda dapat mulai membuat panggilan ke layanan, menggunakan metode yang ditetapkan oleh antarmuka. - Untuk memutus koneksi dari layanan, panggil
unbindService()
.Jika klien Anda tetap terikat ke layanan saat aplikasi Anda menghapus klien, penghapusan tersebut akan menyebabkan ikatan klien terputus. Praktik yang lebih baik adalah dengan memutus ikatan klien begitu selesai berinteraksi dengan layanan. Hal itu memungkinkan layanan yang tidak ada aktivitas untuk dimatikan. Untuk informasi selengkapnya tentang waktu yang tepat untuk mengikat dan melepas, lihat Catatan tambahan.
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
:
Kotlin
var mService: LocalService val mConnection = object : ServiceConnection { // Called when the connection with the service is established override fun onServiceConnected(className: ComponentName, service: IBinder) { // Because we have bound to an explicit // service that is running in our own process, we can // cast its IBinder to a concrete class and directly access it. val binder = service as LocalService.LocalBinder mService = binder.getService() mBound = true } // Called when the connection with the service disconnects unexpectedly override fun onServiceDisconnected(className: ComponentName) { Log.e(TAG, "onServiceDisconnected") mBound = false } }
Java
LocalService mService; private ServiceConnection mConnection = new ServiceConnection() { // Called when the connection with the service is established public void onServiceConnected(ComponentName className, IBinder service) { // Because we have bound to an explicit // service that is running in our own process, we can // cast its IBinder to a concrete class and directly access it. LocalBinder binder = (LocalBinder) service; mService = binder.getService(); mBound = true; } // Called when the connection with the service disconnects unexpectedly public void onServiceDisconnected(ComponentName className) { Log.e(TAG, "onServiceDisconnected"); mBound = false; } };
Dengan ServiceConnection
ini, klien bisa mengikat ke layanan dengan meneruskannya
ke bindService()
, seperti yang ditampilkan pada contoh berikut:
Kotlin
Intent(this, LocalService::class.java).also { intent -> bindService(intent, connection, Context.BIND_AUTO_CREATE) }
Java
Intent intent = new Intent(this, LocalService.class); bindService(intent, connection, Context.BIND_AUTO_CREATE);
- Parameter pertama
bindService()
adalahIntent
yang secara eksplisit menyebutkan layanan yang akan diikat.Perhatian: Jika Anda menggunakan intent untuk mengikat
Service
, pastikan aplikasi Anda sudah aman menggunakan intent eksplisit. Menggunakan intent implisit untuk memulai layanan dapat membahayakan keamanan, karena Anda tidak dapat memastikan layanan yang akan merespons intent tersebut, dan pengguna tidak dapat melihat layanan yang dimulai. Mulai dari Android 5.0 (API level 21), sistem akan melontarkan pengecualian jika Anda memanggilbindService()
dengan intent implisit. - Parameter kedua adalah objek
ServiceConnection
. - Parameter ketiga adalah tanda yang menunjukkan opsi pengikatan. Tanda ini biasanya harus berupa
BIND_AUTO_CREATE
agar dapat membuat layanan jika belum aktif. Nilai yang memungkinkan lainnya adalahBIND_DEBUG_UNBIND
danBIND_NOT_FOREGROUND
, atau0
bila tidak satu pun.
Catatan tambahan
Berikut ini beberapa catatan penting tentang pengikatan ke layanan:
- Anda harus selalu menjebak pengecualian
DeadObjectException
, yang dilontarkan jika koneksi terputus. Inilah satu-satunya pengecualian yang dilontarkan oleh metode jauh. - Objek adalah acuan yang dihitung lintas proses.
- Anda biasanya harus menyambungkan pengikatan dan
pelepasan ikatan selama momen pembuatan dan penghapusan siklus proses klien, seperti
yang dijelaskan dalam contoh berikut:
- Jika hanya perlu berinteraksi dengan layanan saat aktivitas terlihat, Anda
harus mengikat selama
onStart()
dan melepas ikatan selamaonStop()
. - Jika Anda ingin aktivitas menerima tanggapan bahkan saat dihentikan di
latar belakang, Anda dapat mengikat selama
onCreate()
dan melepas ikatan selamaonDestroy()
. Berhati-hatilah karena hal ini berarti aktivitas Anda perlu menggunakan layanan selama dijalankan (sekalipun di latar belakang), jadi jika layanan berada dalam proses lain, Anda menambah beban proses dan memperbesar kemungkinan dimatikan sistem.
Catatan: Anda biasanya tidak bisa mengikat dan melepas ikatan selama
onResume()
danonPause()
aktivitas, karena callback ini terjadi pada setiap transisi siklus proses dan Anda harus meminimalkan pemrosesan yang terjadi pada transisi ini. Selain itu, jika banyak aktivitas dalam aplikasi Anda mengikat ke layanan yang sama dan terdapat transisi antara dua aktivitas, layanan dapat dihapus dan dibuat lagi ketika aktivitas saat ini melepas ikatan (selama jeda) sebelum aktivitas berikutnya mengikat (selama lanjutkan). Transisi aktivitas ini untuk cara aktivitas mengoordinasikan siklus prosesnya dijelaskan dalam dokumen Aktivitas. - Jika hanya perlu berinteraksi dengan layanan saat aktivitas terlihat, Anda
harus mengikat selama
Untuk kode contoh selengkapnya, yang menampilkan cara mengikat ke layanan, lihat class
RemoteService.java
dalam ApiDemos.
Mengelola siklus proses layanan terikat
Bila 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.

Gambar 1. Siklus proses untuk layanan yang dimulai dan juga mengizinkan pengikatan.
Untuk informasi selengkapnya tentang siklus proses layanan yang telah dimulai, lihat dokumen Layanan.