Um serviço vinculado é o servidor em uma interface cliente-servidor. Ele permite que componentes, como atividades, sejam vinculados ao serviço, enviem solicitações, recebam respostas e realizem comunicação entre processos (IPC). Um serviço vinculado geralmente existe somente enquanto serve a outro componente do aplicativo e não é executado em segundo plano indefinidamente.
Este documento descreve como criar um serviço vinculado, inclusive como realizar a vinculação ao serviço em outros componentes do aplicativo. Para mais informações sobre serviços em geral, por exemplo, como enviar notificações de um serviço e definir a execução dele em primeiro plano, consulte Visão geral dos serviços.
Noções básicas
Um serviço vinculado é uma implementação da classe Service
que permite
que outros aplicativos sejam vinculados e interajam com ele. Para fornecer a vinculação a um
serviço, implemente o método de callback onBind()
. Esse
método retorna um objeto IBinder
que define a interface de programação que
os clientes podem usar para interagir com o serviço.
Vincular a um serviço iniciado
Conforme discutido na Visão geral dos serviços, é possível criar um serviço que já tenha sido iniciado e vinculado. Ou seja, é possível iniciar um serviço chamando startService()
, que permite que o serviço seja executado indefinidamente. Você também pode permitir que um cliente se vincule ao serviço
chamando bindService()
.
Se você permitir que o serviço seja iniciado e vinculado, quando ele for iniciado,
o sistema não o destruirá quando todos os clientes se desvincularem.
Em vez disso,
interrompa o serviço explicitamente chamando stopSelf()
ou stopService()
.
Apesar de normalmente você implementar onBind()
ou onStartCommand()
, às vezes
é necessário
implementar ambos. Por exemplo, para um reprodutor de música, pode ser útil deixar o serviço em execução
indefinidamente, além de fornecer vinculação. Dessa forma, uma atividade pode iniciar o serviço para reproduzir algumas
músicas, e a música continuará sendo tocada mesmo se o usuário sair do aplicativo. Em seguida, quando o usuário
voltar ao aplicativo, a atividade poderá ser vinculada ao serviço para retomar o controle da
reprodução.
Para mais informações sobre o ciclo de vida do serviço ao adicionar a vinculação a um serviço iniciado, consulte a seção Gerenciar o ciclo de vida de um serviço vinculado.
O cliente poderá vincular-se a um serviço chamando
bindService()
. Quando isso ocorre, é preciso
fornecer uma implementação de ServiceConnection
, que
monitora a conexão com o serviço. O valor de retorno de
bindService()
indica se o
serviço solicitado existe e se o cliente tem permissão para acessá-lo.
Quando
o sistema Android cria a conexão entre o cliente e o serviço, ele
chama onServiceConnected()
no ServiceConnection
. O método
onServiceConnected()
inclui um argumento IBinder
, que o cliente usa para se comunicar com o serviço vinculado.
Você pode conectar vários clientes a um serviço simultaneamente. No entanto, o
sistema armazena em cache o canal de comunicação do serviço IBinder
.
Em outras palavras, o sistema chama o método onBind()
do serviço para gerar o IBinder
somente quando o primeiro
cliente é vinculado. Assim, o sistema entrega o mesmo IBinder
a
todos os outros clientes vinculados ao mesmo serviço, sem chamar
onBind()
novamente.
Quando o último cliente se desvincula do serviço, o sistema o destrói, a menos que
ele tenha sido iniciado usando startService()
.
Ao implementar o serviço vinculado, o mais importante é definir a interface
que o método de callback onBind()
retornará. A seção a seguir
discute várias maneiras de definir a interface
IBinder
do serviço.
Criar um serviço vinculado
Ao criar um serviço que fornece vinculação, você precisa fornecer um IBinder
que ofereça a interface de programação que os clientes podem usar para interagir com o serviço. Há
três maneiras possíveis de definir a interface:
- Estender a classe Binder
- Se o serviço for particular para seu próprio aplicativo e executado no mesmo processo
que o cliente, o que é comum, crie sua interface estendendo a classe
Binder
e retornando uma instância dela deonBind()
. O cliente receberáBinder
e poderá usá-lo para acessar os métodos públicos disponíveis na implementação deBinder
ou deService
.Essa é a técnica mais recomendada quando o serviço é meramente um worker de segundo plano para o próprio aplicativo. O único caso de uso quando essa não é a maneira recomendada de criar sua interface é se o serviço for usado por outros aplicativos ou em processos separados.
- Usar um Messenger
- Caso você precise que a interface funcione em diferentes processos, é possível criar
uma interface para o serviço com um
Messenger
. Dessa maneira, o serviço define umHandler
que responde a diferentes tipos de objetosMessage
.Esse
Handler
é a base para umMessenger
que pode compartilhar umIBinder
com o cliente, permitindo que ele envie comandos ao serviço usando objetosMessage
. Além disso, o cliente pode definir o próprioMessenger
para que o serviço possa enviar as mensagens de volta.Essa é a maneira mais simples de estabelecer a comunicação entre processos (IPC), já que o
Messenger
coloca todas as solicitações em fila em uma única linha de execução para que você não precise projetar o serviço para que seja seguro para linhas de execução. - Usar AIDL
- A linguagem de definição de interface do Android (AIDL) decompõe objetos em
primitivos que o sistema operacional pode entender e os organiza em processos para realizar
IPC. A técnica anterior, usando o
Messenger
, tem base na AIDL como a estrutura subjacente.Como mencionado na seção anterior, o
Messenger
cria uma fila de todas as solicitações do cliente em uma única linha de execução, para que o serviço receba uma solicitação por vez. No entanto, se você quiser que o serviço processe várias solicitações simultaneamente, poderá usar a AIDL diretamente. Nesse caso, seu serviço precisa ser seguro para linhas de execução e ser capaz de usar várias linhas de execução.Para usar a AIDL diretamente, crie um arquivo
.aidl
que defina a interface de programação. As ferramentas do SDK do Android usam esse arquivo para gerar uma classe abstrata que implementa a interface e processa a IPC, que pode ser estendida dentro do serviço.
Observação:para a maioria dos aplicativos, a AIDL não é a melhor escolha para criar um serviço vinculado, porque pode exigir recursos de várias linhas de execução e resultar em uma implementação mais complicada. Portanto, este documento não discute como usá-lo para seu serviço. Se você tiver certeza de que precisa usar a AIDL diretamente, consulte o documento AIDL.
Estender a classe Binder
Se apenas o aplicativo local usar o serviço e ele não precisar
trabalhar entre processos,
você poderá implementar sua própria classe Binder
, que fornece ao cliente acesso direto
a métodos públicos no serviço.
Observação: isso funcionará somente se o cliente e o serviço estiverem no mesmo aplicativo e processo, o que é muito comum. Por exemplo, isso funciona bem para um aplicativo de música que precisa vincular uma atividade ao próprio serviço que está tocando música em segundo plano.
Veja aqui como configurar esse recurso:
- No seu serviço, crie uma instância de
Binder
que realize uma das seguintes ações:- Contenha métodos públicos que o cliente possa chamar.
- Retorne ao cliente a instância
Service
atual, que tenha métodos públicos que ele possa chamar. - Retorne uma instância de outra classe hospedada pelo serviço com métodos públicos que o cliente possa chamar.
- Retorne essa instância de
Binder
do método de callbackonBind()
. - No cliente, receba o
Binder
do método de callbackonServiceConnected()
e faça chamadas para o serviço vinculado usando os métodos fornecidos.
Observação: o serviço e o cliente precisam estar no mesmo aplicativo para que o cliente possa transmitir o objeto retornado e chamar as APIs adequadamente. O serviço e o cliente também precisam estar no mesmo processo, porque essa técnica não executa nenhum gerenciamento entre processos.
Por exemplo, veja um serviço que fornece aos clientes acesso aos métodos com uma
implementação de 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); } }
O LocalBinder
fornece o método getService()
para que os clientes recuperem a
instância atual de LocalService
. Isso permite que os clientes chamem métodos públicos no
serviço. Por exemplo, eles podem chamar getRandomNumber()
no serviço.
Veja uma atividade que se vincula a LocalService
e chama getRandomNumber()
quando um botão é pressionado:
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 is something that might hang, then put this request // 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 is something that might hang, then put this request // 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; } }; }
O exemplo anterior mostra como o cliente se vincula ao serviço usando uma implementação de
ServiceConnection
e o callback onServiceConnected()
. A próxima
seção fornece mais informações sobre esse processo de vinculação ao serviço.
Observação:no exemplo anterior, o
método onStop()
desvincula o cliente do serviço.
Desvincule os clientes dos serviços em momentos apropriados, conforme discutido na seção Outras observações.
Para ver mais exemplos de código, consulte as classes
LocalService.java
e
LocalServiceActivities.java
em ApiDemos.
Usar um mensageiro
Caso você precise que o serviço se comunique com processos remotos, é possível usar um
Messenger
para fornecer a interface ao serviço. Essa técnica permite
estabelecer comunicação entre processos (IPC) sem precisar usar a AIDL.
Usar um Messenger
para sua interface é
mais fácil que usar a AIDL, já que Messenger
cria
uma fila com todas as chamadas para o serviço. Uma interface AIDL pura envia solicitações simultâneas para o
serviço, que precisa gerenciar várias linhas de execução.
Para a maioria dos aplicativos, o serviço não precisa realizar várias linhas de execução. Portanto, usar Messenger
permite que o serviço processe uma chamada por vez. Se for importante
que o serviço tenha várias linhas de execução, use a AIDL para definir sua interface.
Veja a seguir um resumo sobre como usar um Messenger
.
- O serviço implementa um
Handler
que recebe um callback para cada chamada de um cliente. - O serviço usa o
Handler
para criar um objetoMessenger
(que é uma referência paraHandler
). - O
Messenger
cria umIBinder
que o serviço retorna aos clientes deonBind()
. - Os clientes usam
IBinder
para instanciar oMessenger
(que faz referência aoHandler
do serviço), que usam para enviar objetosMessage
para o serviço. - O serviço recebe cada
Message
no respectivoHandler
, especificamente, no métodohandleMessage()
.
Dessa forma, não há métodos para o cliente chamar no serviço. Em vez disso, o
cliente envia mensagens (objetos Message
) que o serviço
recebe
no Handler
.
Veja a seguir um exemplo simples de serviço que usa uma interface 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(); } }
O método handleMessage()
no
Handler
é onde o serviço recebe a Message
e decide o que fazer com base no membro what
.
Tudo o que o cliente precisa fazer é criar um Messenger
com base no IBinder
retornado pelo serviço e enviar uma mensagem usando send()
. Por exemplo, veja uma atividade que se vincula ao
serviço e envia a mensagem MSG_SAY_HELLO
a ele:
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; } } }
O exemplo não mostra como o serviço pode responder ao cliente.
Caso queira que o
serviço responda, também será necessário criar um Messenger
no cliente.
Em seguida, quando o cliente receber o callback de onServiceConnected()
ele enviará uma Message
ao serviço que inclui
o Messenger
do cliente no parâmetro replyTo
do método send()
.
Veja um exemplo de como fornecer mensagens bidirecionais nas amostras
MessengerService.java
(serviço) e
MessengerServiceActivities.java
(cliente).
Vincular a um serviço
Componentes de aplicativo (clientes) podem se vincular a um serviço chamando
bindService()
. O sistema Android,
em seguida, chama o método onBind()
do serviço, que retorna um IBinder
para interagir com
o serviço.
A vinculação é assíncrona, e bindService()
é retornado imediatamente sem retornar IBinder
ao
cliente. Para receber o IBinder
, o cliente precisa criar uma
instância de ServiceConnection
e transmiti-la para bindService()
. O ServiceConnection
inclui um método de callback que o
sistema chama para enviar o IBinder
.
Observação: somente atividades, serviços e provedores de conteúdo podem se vincular a um serviço. Isso não é possível em um broadcast receiver.
Para vincular um serviço do seu cliente, siga estas etapas:
- Implemente
ServiceConnection
.Sua implementação precisa substituir dois métodos de callback:
onServiceConnected()
- O sistema chama isso para entregar o
IBinder
retornado pelo métodoonBind()
do serviço. onServiceDisconnected()
- O sistema Android chama isso quando a conexão com o serviço é perdida inesperadamente, como quando o serviço falha ou é encerrado. Isso não é chamado quando o cliente desfaz a vinculação.
- Chame
bindService()
, transmitindo a implementaçãoServiceConnection
.Observação: se o método retornar “falso”, seu cliente não terá uma conexão válida com o serviço. No entanto, chame
unbindService()
no cliente. Caso contrário, o cliente impedirá que o serviço seja encerrado quando estiver inativo. - Quando o sistema chama o método de callback
onServiceConnected()
, é possível fazer chamadas para o serviço usando os métodos definidos pela interface. - Para se desconectar de um serviço, chame
unbindService()
.Se o cliente ainda estiver vinculado a um serviço quando o app o destruir, a destruição fará com que o cliente seja desvinculado. É melhor desvincular o cliente assim que ele terminar de interagir com o serviço. Isso permite que o serviço inativo seja encerrado. Para saber mais sobre os momentos adequados para vinculação e desvinculação, consulte a seção Outras observações.
O exemplo a seguir conecta o cliente ao serviço criado anteriormente
estendendo a classe Binder. Portanto, tudo o que precisa fazer é transmitir o
IBinder
retornado para a classe LocalBinder
e solicitar a instância 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; } };
Com esse ServiceConnection
, o cliente pode se vincular a um serviço
transmitindo-o
para bindService()
, como mostrado neste exemplo:
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);
- O primeiro parâmetro de
bindService()
é umIntent
que nomeia explicitamente o serviço que será vinculado.Cuidado:se você usar uma intent para vincular um
Service
, use uma intent explícita para verificar se o app é seguro. O uso de uma intent implícita para iniciar um serviço representa um risco de segurança, porque não é possível determinar qual serviço responde à intent, e o usuário não pode ver qual serviço é iniciado. A partir do Android 5.0 (API de nível 21), o sistema gera uma exceção se você chamabindService()
com uma intent implícita. - O segundo parâmetro é o objeto
ServiceConnection
. - O terceiro parâmetro é uma sinalização que indica opções de vinculação, geralmente
BIND_AUTO_CREATE
, para criar o serviço se ele ainda não estiver ativo. Outros valores possíveis sãoBIND_DEBUG_UNBIND
,BIND_NOT_FOREGROUND
ou0
, se não houver nenhum.
Outras observações
A seguir, há algumas observações importantes sobre a vinculação a um serviço:
- Sempre capture exceções
DeadObjectException
, que são geradas quando a conexão apresenta erros. Essa é a única exceção lançada por métodos remotos. - Objetos são referências contadas entre processos.
- Geralmente, você pareia a vinculação e a desvinculação durante os
momentos de ampliação e queda correspondentes do ciclo de vida do cliente, conforme descrito nos
exemplos a seguir:
- Caso você precise interagir com o serviço apenas enquanto a atividade estiver visível, vincule durante
onStart()
e desvincule duranteonStop()
. - Caso queira que sua atividade receba respostas mesmo quando for interrompida em
segundo plano, vincule durante
onCreate()
e desvincule duranteonDestroy()
. Esteja ciente de que isso implica que sua atividade precisa usar o serviço durante toda a execução, mesmo em segundo plano. Portanto, quando o serviço está em outro processo, você aumenta o peso do processo e é mais provável que ele seja encerrado pelo sistema.
Observação:geralmente, você não vincula e se desvincula durante os callbacks
onResume()
eonPause()
da atividade, porque eles ocorrem em todas as transições do ciclo de vida. Mantenha o processamento que ocorre nessas transições ao mínimo.Além disso, se várias atividades no seu aplicativo se vincularem ao mesmo serviço e houver uma transição entre duas dessas atividades, o serviço poderá ser destruído e recriado à medida que a atividade atual se desvincula (durante a pausa) antes da vinculação seguinte (durante a retomada). Essa transição de atividade para como as atividades coordenam os ciclos de vida é descrita em Ciclo de vida da atividade.
- Caso você precise interagir com o serviço apenas enquanto a atividade estiver visível, vincule durante
Para ver mais exemplos de código que mostram como vincular a um serviço, consulte a classe
RemoteService.java
no ApiDemos.
Gerenciar o ciclo de vida de um serviço vinculado
Quando um serviço é desvinculado de todos os clientes, o sistema Android o destrói
(a menos que tenha sido iniciado usando
startService()
).
Assim, não é necessário gerenciar o ciclo de vida do serviço se ele for
puramente um serviço vinculado. O sistema Android gerencia o app de acordo com a
vinculação a algum cliente ou não.
No entanto, se você optar por implementar o método de callback onStartCommand()
, interrompa o serviço explicitamente, porque ele agora será considerado iniciado. Nesse caso, o serviço permanecerá em execução até
ser interrompido com stopSelf()
ou que outro componente chame stopService()
, independentemente de estar ou não vinculado a qualquer
cliente.
Além disso, se o serviço for iniciado e aceitar vinculação, quando o sistema chamar
o método onUnbind()
, será possível retornar
true
se você quiser receber uma chamada para onRebind()
na próxima vez que um cliente se vincular ao serviço. onRebind()
retorna "void", mas o cliente ainda recebe o IBinder
no callback
onServiceConnected()
.
A figura a seguir ilustra a lógica desse tipo de ciclo de vida.
Para mais informações sobre o ciclo de vida de um serviço iniciado, consulte a Visão geral dos serviços.