page.title=Serviços @jd:body
Um {@link android.app.Service} é um componente do aplicativo que pode realizar operações longas e não fornece uma interface do usuário. Outro componente do aplicativo pode iniciar um serviço e ele continuará em execução em segundo plano mesmo que o usuário alterne para outro aplicativo. Além disso, um componente poderá vincular-se a um serviço para interagir com ele e até estabelecer comunicação entre processos (IPC). Por exemplo, um serviço pode lidar com operações de rede, reproduzir música, executar E/S de arquivos, ou interagir com um provedor de conteúdo, tudo a partir do segundo plano.
Um serviço pode essencialmente ter duas formas:
Apesar de esta documentação discutir os dois tipos de serviços separadamente, um serviço pode funcionar das duas maneiras — ele pode ser iniciado (para permanecer em execução indefinidamente) e também permitir a vinculação. Basta você implementar alguns métodos de retorno de chamada: {@link android.app.Service#onStartCommand onStartCommand()} para permitir que os componentes iniciem o serviço e {@link android.app.Service#onBind onBind()} para permitir a vinculação.
Se o aplicativo for iniciado, vinculado ou ambos, qualquer componente do aplicativo poderá usar o serviço (mesmo a partir de um aplicativo separado), da mesma forma que qualquer componente poderá usar uma atividade — iniciando com uma {@link android.content.Intent}. No entanto, é possível declarar o serviço como privado, no arquivo do manifesto, e bloquear o acesso de outros aplicativos. Isto é discutido com mais detalhes na seção Declaração do serviço no manifesto.
Atenção: um serviço é executado no encadeamento principal em seu processo de hospedagem — o serviço não cria seu próprio encadeamento e não é executado em um processo separado (salvo se especificado). Isso significa que, se o serviço for realizar qualquer trabalho intensivo de CPU ou operações de bloqueio (como reprodução de MP3 ou rede), você deve criar um novo encadeamento dentro do serviço. Usando um encadeamento separado, você reduzirá o risco da ocorrência de erros de Aplicativo não respondendo (ANR) e o encadeamento principal do aplicativo poderá permanecer dedicado à interação do usuário com as atividades.
Um serviço é simplesmente um componente que pode ser executado em segundo plano mesmo quando o usuário não está interagindo com o aplicativo. Portanto, um serviço deve ser criado somente se for realmente necessário.
Caso precise realizar trabalhos fora do encadeamento principal, mas somente enquanto o usuário estiver interagindo com o aplicativo, então você deve criar um novo encadeamento e não um serviço. Por exemplo, se quiser reproduzir músicas, mas somente enquanto a atividade estiver em execução, você pode criar um encadeamento em {@link android.app.Activity#onCreate onCreate()}, iniciando a execução em {@link android.app.Activity#onStart onStart()}, e interrompendo em {@link android.app.Activity#onStop onStop()}. Considere também usar {@link android.os.AsyncTask} ou {@link android.os.HandlerThread}, em vez de a classe tradicional {@link java.lang.Thread}. Consulte o documento Processos e encadeamentos para obter mais informações sobre encadeamentos.
Lembre-se de que, se usar um serviço, ele ainda será executado no encadeamento principal do aplicativo por padrão, portanto deve-se criar um novo encadeamento dentro do serviço se ele realizar operações intensivas ou de bloqueio.
Para criar um serviço, você deve criar uma subclasse de {@link android.app.Service} (ou uma das subclasses existentes). Na implementação, será necessário substituir alguns métodos de retorno de chamada que lidem com aspectos essenciais do ciclo de vida do serviço e forneçam um mecanismo para vincular componentes ao serviço, se apropriado. Os dois métodos mais importantes de retorno de chamada que você deve substituir são:
Se um componente iniciar o serviço chamando {@link android.content.Context#startService startService()} (o que resulta em uma chamada para {@link android.app.Service#onStartCommand onStartCommand()}), o serviço permanecerá em execução até ser interrompido por conta própria com {@link android.app.Service#stopSelf()} ou por outro componente chamando {@link android.content.Context#stopService stopService()}.
Se um componente chamar {@link android.content.Context#bindService bindService()} para criar o serviço (e {@link android.app.Service#onStartCommand onStartCommand()} não for chamado), o serviço será executado somente enquanto o componente estiver vinculado a ele. Quando o serviço for desvinculado de todos os clientes, o sistema o destruirá.
O sistema Android forçará a interrupção de um serviço somente quando a memória estiver baixa e precisar recuperar os recursos do sistema para a atividade com que o usuário estiver interagindo. Se o serviço estiver vinculado a uma atividade que o usuário tenha atribuído foco, é menos provável que ele seja eliminado. E, se o serviço for declarado para ser executado em primeiro plano (discutido posteriormente), então ele quase nunca será eliminado. Caso contrário, se o serviço for iniciado e estiver em uma longa execução, o sistema reduzirá sua posição na lista de tarefas de segundo plano no decorrer do tempo e o serviço se tornará altamente suscetível à eliminação — se o serviço for iniciado, então você deve programá-lo para lidar com reinicializações pelo sistema. Se o sistema eliminar o seu serviço, ele reiniciará assim que os recursos estiverem disponíveis novamente (apesar de isto também depender do valor que você retornar de {@link android.app.Service#onStartCommand onStartCommand()}, como discutido a seguir). Para obter mais informações sobre quando o sistema deve destruir um serviço, consulte o documento Processos e encadeamentos .
Nas seguintes seções, você verá como é possível criar cada tipo de serviço e como usá-los a partir de outros componentes do aplicativo.
Como atividades (e outros componentes), você deve declarar todos os serviços no arquivo de manifesto do aplicativo.
Para declarar o serviço, adicione um elemento {@code <service>} como filho do elemento {@code <application>} . Por exemplo:
<manifest ... > ... <application ... > <service android:name=".ExampleService" /> ... </application> </manifest>
Consulte a referência de elemento {@code <service>} para obter mais informações sobre como declarar o serviço no manifesto.
É possível incluir outros atributos no elemento {@code <service>} para definir propriedades como permissões necessárias para iniciar o serviço e o processo em que o serviço deve ser executado. O atributo {@code android:name} é o único necessário — ele especifica o nome da classe do serviço. Ao publicar o aplicativo, não deve-se alterar-lhe o nome porque, se isso acontecer, há riscos de ocorrência de erros de código devido à dependência de intenções explícitas para iniciar ou vincular o serviço (leia a publicação do blogue, Coisas que não podem mudar).
Para garantir a segurança do aplicativo, sempre use uma intenção explícita ao iniciar ou vincular {@link android.app.Service} e não declare filtros de intenção para o serviço. Caso seja essencial permitir alguma ambiguidade, como qual serviço deve ser usado para iniciar, é possível fornecer filtros de intenções para os serviços e excluir o nome do componente de {@link android.content.Intent}, mas é preciso definir o pacote para a intenção com {@link android.content.Intent#setPackage setPackage()}, que fornece desambiguidade suficiente para o serviço alvo.
Além disso, é possível garantir que o serviço esteja disponível somente para o aplicativo incluindo o atributo {@code android:exported} e definindo-o como {@code "false"}. Isto impede efetivamente que outros aplicativos iniciem o serviço, mesmo usando uma intenção explícita.
Um serviço iniciado é o que outro componente inicia chamando {@link android.content.Context#startService startService()}, resultando em uma chamada para o método {@link android.app.Service#onStartCommand onStartCommand()} do serviço.
Quando um serviço é iniciado, ele tem um ciclo de vida que não depende do componente que o iniciou. Além disso, o serviço pode ser executado em segundo plano indefinidamente, mesmo se o componente que o iniciou for eliminado. Além disso, o serviço deve ser interrompido quando o seu trabalho for realizado, chamando {@link android.app.Service#stopSelf stopSelf()}. Outros componentes podem interrompê-lo chamando {@link android.content.Context#stopService stopService()}.
Um componente do aplicativo, como uma atividade, pode iniciar o serviço chamando {@link android.content.Context#startService startService()} e passando {@link android.content.Intent}, que especifica o serviço e inclui os dados para o serviço usar. O serviço recebe esta {@link android.content.Intent} no método {@link android.app.Service#onStartCommand onStartCommand()}.
Por exemplo, presuma que uma atividade precise salvar alguns dados em um banco de dados on-line. A atividade pode iniciar um serviço de acompanhamento e entregar a ele os dados a salvar passando uma intenção para {@link android.content.Context#startService startService()}. O serviço recebe a intenção em {@link android.app.Service#onStartCommand onStartCommand()}, conecta-se à Internet e realiza a transação no banco de dados. Quando a operação é concluída, o serviço é interrompido e destruído.
Atenção: um serviço é executado no mesmo processo que o aplicativo em que ele é declarado e no encadeamento principal do aplicativo, por padrão. Portanto, se o serviço realizar operações intensivas ou de bloqueio quando o usuário interagir com uma atividade do mesmo aplicativo, diminuirá o desempenho da atividade. Para evitar impacto no desempenho do aplicativo, deve-se iniciar um novo encadeamento dentro do serviço.
Geralmente, há duas classes que podem ser estendidas para criar um serviço iniciado:
As seguintes seções descrevem como é possível implementar o serviço usando uma dessas classes.
Como a maioria dos serviços não precisam lidar com várias solicitações simultaneamente (o que pode ser perigoso para situações de vários encadeamentos), é melhor se o serviço for implementado usando a classe {@link android.app.IntentService}.
O {@link android.app.IntentService} faz o seguinte:
Tudo isso adiciona-se ao fato de que basta implementar {@link android.app.IntentService#onHandleIntent onHandleIntent()} para fazer o trabalho fornecido pelo cliente (embora também seja necessário fornecer um pequeno construtor para o serviço).
A seguir há um exemplo de implementação de {@link android.app.IntentService}:
public class HelloIntentService extends IntentService { /** * A constructor is required, and must call the super {@link android.app.IntentService#IntentService} * constructor with a 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 5 seconds. long endTime = System.currentTimeMillis() + 5*1000; while (System.currentTimeMillis() < endTime) { synchronized (this) { try { wait(endTime - System.currentTimeMillis()); } catch (Exception e) { } } } } }
É tudo que você precisa: um construtor e uma implementação de {@link android.app.IntentService#onHandleIntent onHandleIntent()}.
Caso decida substituir outros métodos de retorno de chamada, como {@link android.app.IntentService#onCreate onCreate()}, {@link android.app.IntentService#onStartCommand onStartCommand()} ou {@link android.app.IntentService#onDestroy onDestroy()}, certifique-se de chamar a super-implementação para que o {@link android.app.IntentService} possa lidar adequadamente com a vida do encadeamento de trabalho.
Por exemplo, {@link android.app.IntentService#onStartCommand onStartCommand()} deve retornar a implementação padrão (que é como a intenção é entregue para {@link android.app.IntentService#onHandleIntent onHandleIntent()}):
@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); }
Além de {@link android.app.IntentService#onHandleIntent onHandleIntent()}, o único método que não precisa ser usado para chamar a superclasse é {@link android.app.IntentService#onBind onBind()} (mas é necessário implementá-lo se o serviço permitir vinculações).
Na próxima seção, você verá como o mesmo tipo de serviço é implementado ao estender a classe de base {@link android.app.Service}, que possui muito mais códigos, mas que pode ser apropriada para lidar com solicitações de inicialização simultâneas.
Como você viu na seção anterior, o uso de {@link android.app.IntentService} torna a implementação de um serviço iniciado muito simples. Se, no entanto, você precisa do serviço para realizar vários encadeamentos (em vez de processar as solicitações de inicialização por meio de uma fila de trabalho), é possível estender a classe {@link android.app.Service} para lidar com cada intenção.
Para efeito de comparação, o seguinte exemplo de código é uma implementação da classe {@link android.app.Service} que realiza exatamente o mesmo trabalho que o exemplo acima usando {@link android.app.IntentService}. Ou seja, para cada solicitação de inicialização, ela usa um encadeamento de trabalho para realizar o trabalho e processa apenas uma solicitação por vez.
public class HelloService extends Service { private Looper mServiceLooper; private ServiceHandler mServiceHandler; // Handler that receives messages from the thread private final class ServiceHandler extends Handler { public ServiceHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { // Normally we would do some work here, like download a file. // For our sample, we just sleep for 5 seconds. long endTime = System.currentTimeMillis() + 5*1000; while (System.currentTimeMillis() < endTime) { synchronized (this) { try { wait(endTime - System.currentTimeMillis()); } catch (Exception e) { } } } // Stop the service using the startId, so that we don't stop // the service in the middle of handling another job stopSelf(msg.arg1); } } @Override public void onCreate() { // Start up the thread running the service. Note that we create a // separate thread because the service normally runs in the process's // main thread, which we don't want to block. We also make it // background priority so CPU-intensive work will not disrupt our UI. HandlerThread thread = new HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND); thread.start(); // Get the HandlerThread's Looper and use it for our Handler mServiceLooper = thread.getLooper(); mServiceHandler = new ServiceHandler(mServiceLooper); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show(); // For each start request, send a message to start a job and deliver the // start ID so we know which request we're stopping when we finish the job Message msg = mServiceHandler.obtainMessage(); msg.arg1 = startId; mServiceHandler.sendMessage(msg); // If we get killed, after returning from here, restart return START_STICKY; } @Override public IBinder onBind(Intent intent) { // We don't provide binding, so return null return null; } @Override public void onDestroy() { Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show(); } }
Como pode ver, é muito mais trabalhoso do que usar {@link android.app.IntentService}.
No entanto, como você lida com cada chamada de {@link android.app.Service#onStartCommand onStartCommand()}, é possível realizar várias solicitações simultaneamente. Isso não é o que este exemplo faz, mas, se for o que quer, é possível criar um novo encadeamento para cada solicitação e executá-las na hora (em vez de esperar que a solicitação anterior seja concluída).
Observe que o método {@link android.app.Service#onStartCommand onStartCommand()} deve retornar um número inteiro. O número inteiro é um valor que descreve como o sistema deve continuar o serviço no evento em que o sistema o eliminar (como discutido acima, a implementação padrão de {@link android.app.IntentService} lida com isto, apesar de ser possível modificá-lo). O valor de retorno de {@link android.app.Service#onStartCommand onStartCommand()} deve ser uma das seguintes constantes:
Para obter mais informações sobre esses valores de retorno, veja a documentação de referência vinculada a cada constante.
É possível iniciar um dispositivo de uma atividade ou outro componente do aplicativo passando uma {@link android.content.Intent} a {@link android.content.Context#startService startService()}. O sistema Android chama o método {@link android.app.Service#onStartCommand onStartCommand()} do serviço e passa a ele a {@link android.content.Intent} (nunca deve-se chamar {@link android.app.Service#onStartCommand onStartCommand()} diretamente).
Por exemplo, uma atividade pode iniciar o serviço de exemplo na seção anterior ({@code HelloSevice}) usando uma intenção explícita com {@link android.content.Context#startService startService()}:
Intent intent = new Intent(this, HelloService.class); startService(intent);
O método {@link android.content.Context#startService startService()} retorna imediatamente e o sistema Android chama o método {@link android.app.Service#onStartCommand onStartCommand()} do serviço. Se o serviço não estiver em execução, o sistemo primeiro chama {@link android.app.Service#onCreate onCreate()} e, em seguida, chama {@link android.app.Service#onStartCommand onStartCommand()}.
Se o serviço não fornecer vinculação, a intenção entregue com {@link android.content.Context#startService startService()} é o único modo de comunicação entre o componente do aplicativo e o serviço. No entanto, se quiser que o serviço envie um resultado de volta, o cliente que iniciar o serviço poderá criar um {@link android.app.PendingIntent} para uma transmissão (com {@link android.app.PendingIntent#getBroadcast getBroadcast()}) e entregá-la ao serviço na {@link android.content.Intent} que iniciar o serviço. O serviço pode então usar a transmissão para entregar um resultado.
Várias solicitações para iniciar o serviço resultam em diversas chamadas correspondentes ao {@link android.app.Service#onStartCommand onStartCommand()} do serviço. No entanto, somente uma solicitação para interromper o serviço (com {@link android.app.Service#stopSelf stopSelf()} ou {@link android.content.Context#stopService stopService()}) é necessária para interrompê-lo.
Um serviço iniciado deve gerenciar seu próprio ciclo de vida. Ou seja, o sistema não interrompe ou elimina o serviço, a não ser que tenha que recuperar a memória do sistema e o serviço continuar em execução depois que {@link android.app.Service#onStartCommand onStartCommand()} retornar. Portanto, o serviço deve ser interrompido chamando {@link android.app.Service#stopSelf stopSelf()} ou outro componente pode interrompê-lo chamando {@link android.content.Context#stopService stopService()}.
Ao solicitar o interrompimento com {@link android.app.Service#stopSelf stopSelf()} ou {@link android.content.Context#stopService stopService()}, o sistema elimina o serviço assim que possível.
No entanto, se o serviço lida com várias solicitações para {@link
android.app.Service#onStartCommand onStartCommand()} ao mesmo tempo, não se deve interromper
o serviço ao terminar o processamento de uma solicitação de inicialização, pois é possível
que uma nova solicitação de inicialização tenha ocorrido (interromper no final da primeira solicitação eliminaria a segunda). Para evitar este problema,
é possível usar {@link android.app.Service#stopSelf(int)} para garantir que a solicitação
que interrompe o serviço sempre se baseie na solicitação de inicialização mais recente. Ou seja, ao chamar {@link
android.app.Service#stopSelf(int)}, você passa o ID da solicitação de inicialização (o startId
entregue a {@link android.app.Service#onStartCommand onStartCommand()}) para aquele que solicitação de interrompimento
corresponde. Em seguida, se o serviço receber uma nova solicitação de inicialização antes de ser possível chamar {@link
android.app.Service#stopSelf(int)}, o ID não corresponderá e o serviço não será interrompido.
Atenção: é importante que um aplicativo interrompa seus serviços quando terminar os trabalhos para evitar o desperdício dos recursos do sistema e consumo da bateria. Se necessário, outros componentes podem interromper o serviço chamando {@link android.content.Context#stopService stopService()}. Mesmo se for possível vincular-se ao serviço, deve-se sempre interrompê-lo por conta própria se ele tiver recebido uma chamada de {@link android.app.Service#onStartCommand onStartCommand()}.
Para obter mais informações sobre o ciclo de vida de um serviço, consulte a seção Gerenciamento do ciclo de vida de um serviço abaixo.
Um serviço vinculado permite que componentes de aplicativo sejam vinculados chamando {@link android.content.Context#bindService bindService()} para criar uma conexão de longo prazo (e, geralmente, não permite que os componentes o iniciem chamando {@link android.content.Context#startService startService()}).
Deve-se criar um serviço vinculado quando se deseja interagir com o serviço a partir de atividades e outros componentes no aplicativo ou para expor algumas das funcionalidades do aplicativo para outros aplicativos, por meio de comunicação entre processos (IPC).
Para criar um serviço vinculado, você deve implementar o método de retorno de chamada {@link android.app.Service#onBind onBind()} para retornar um {@link android.os.IBinder} que define a interface para a comunicação com o serviço. Outros componentes de aplicativo podem chamar {@link android.content.Context#bindService bindService()} para recuperar a interface e começar a chamar métodos no serviço. O serviço vive somente para servir o componente do aplicativo ao qual ele está vinculado. Portanto, quando não houver componentes vinculados ao serviço, o sistema o eliminará (não é necessário interromper um serviço vinculado da mesma maneira que quando o serviço é iniciado por meio de {@link android.app.Service#onStartCommand onStartCommand()}).
Para criar um serviço vinculado, a primeira coisa a se fazer é definir a interface que especifica como um cliente pode comunicar-se com o servidor. Esta interface entre o serviço e um cliente deve ser uma implementação de {@link android.os.IBinder} e é o que o serviço deve retornar a partir do método de retorno de chamada {@link android.app.Service#onBind onBind()}. Quando o cliente receber {@link android.os.IBinder}, ele poderá começar a interagir com o serviço por meio da interface.
Vários clientes podem vincular-se ao serviço por vez. Quando um cliente terminar de interagir com o serviço, ele chamará {@link android.content.Context#unbindService unbindService()} para desvincular-se. Quando não houver clientes vinculados ao serviço, o sistema o eliminará.
Há várias maneiras de implementar um serviço vinculado e a implementação é mais complicada que um serviço iniciado. Logo, a discussão sobre serviços vinculados aparece em um documento separado sobre Serviços vinculados.
Quando em execução, um serviço pode notificar o usuário sobre eventos usando Notificações de aviso ou Notificações da barra de status.
Uma notificação de aviso é uma mensagem que aparece na superfície da janela atual por um breve momento antes de desaparecer, enquanto que uma notificação da barra de status fornece um ícone na barra de status com uma mensagem que o usuário pode selecionar para realizar uma ação (como iniciar uma atividade).
Geralmente, uma notificação da barra de status é a melhor técnica quando um trabalho de segundo plano é concluído (como download de arquivo completo) e o usuário pode agir a partir dele. Quando o usuário seleciona a notificação a partir da vista expandida, ela pode iniciar uma atividade (como a vista do arquivo baixado).
Consulte os guias de desenvolvedor Notificações de aviso ou Notificações da barra de status para obter mais informações.
Um serviço de primeiro plano é aquele com que o usuário está ativamente interagindo e não é uma opção para o sistema eliminá-lo quando a memória estiver baixa. Um serviço de primeiro plano deve fornecer uma notificação para a barra de status, que é colocada sob "o cabeçalho "Em andamento", o que significa que a notificação não pode ser dispensada a não ser que o serviço seja interrompido ou removido do primeiro plano.
Por exemplo, um reprodutor de música que reproduz a partir de um serviço deve ser configurado para permanecer em execução em primeiro plano, pois o usuário está prestando atenção em sua operação explicitamente. A notificação na barra de status pode indicar a música atual e permitir que o usuário inicie uma atividade para interagir com o reprodutor de música.
Para solicitar que o serviço seja executado em primeiro plano, chame {@link android.app.Service#startForeground startForeground()}. Este método usa dois parâmetros: um número inteiro que identifica unicamente a notificação e {@link android.app.Notification} para a barra de status. Por exemplo:
Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text), System.currentTimeMillis()); Intent notificationIntent = new Intent(this, ExampleActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); notification.setLatestEventInfo(this, getText(R.string.notification_title), getText(R.string.notification_message), pendingIntent); startForeground(ONGOING_NOTIFICATION_ID, notification);
Atenção: O ID do número inteiro fornecido para {@link android.app.Service#startForeground startForeground()} não deve ser zero.
Para remover o serviço do primeiro plano, chame {@link android.app.Service#stopForeground stopForeground()}. Este método usa um booleano, indicando se deve remover também a notificação da barra de status. Este método não interrompe o serviço. No entanto, se você interromper o serviço enquanto estiver em execução em primeiro plano, a notificação também será removida.
Para obter mais informações sobre notificações, consulte Criação de notificações da barra de status.
O ciclo de vida de um serviço é muito mais simples do que o de uma atividade. No entanto, é ainda mais importante que você preste muita atenção em como o serviço é criado e eliminado, pois ele pode ser executado em primeiro plano sem que o usuário esteja ciente.
O ciclo de vida do serviço — desde quando é criado até ser eliminado — pode seguir dois caminhos:
O serviço é criado quando outro componente chama {@link android.content.Context#startService startService()}. Depois, o serviço permanece em execução indefinidamente e deve interromper-se chamando {@link android.app.Service#stopSelf() stopSelf()}. Outro componente também pode interromper o serviço chamando {@link android.content.Context#stopService stopService()}. Quando o serviço é interrompido, o sistema o elimina.
O serviço é criado quando outro componente (um cliente) chama {@link android.content.Context#bindService bindService()}. O cliente comunica-se com o serviço pela interface {@link android.os.IBinder}. O cliente pode escolher encerrar a conexão chamando {@link android.content.Context#unbindService unbindService()}. Vários clientes podem ser vinculados ao mesmo serviço e, quando todos os vínculos terminam, o sistema destrói o serviço (o serviço não precisa ser interrompido).
Esses dois caminhos não são inteiramente separados. Ou seja, é possível vincular um serviço que já foi iniciado com {@link android.content.Context#startService startService()}. Por exemplo, um serviço de música de segundo plano pode ser iniciado chamando {@link android.content.Context#startService startService()} com uma {@link android.content.Intent} que identifica a música reproduzida. Depois, possivelmente quando o usuário quiser exercer mais controle sobre o reprodutor ou obter informações sobre a música em reprodução, uma atividade pode ser vinculada ao serviço chamando {@link android.content.Context#bindService bindService()}. Em casos como esse, {@link android.content.Context#stopService stopService()} ou {@link android.app.Service#stopSelf stopSelf()} não interrompe o serviço até que todos os clientes sejam desvinculados.
Como uma atividade, um serviço tem um método de ciclo de vida que é possível implementar para monitorar as alterações no estado do serviço e realizar trabalhos em momentos adequados. O seguinte serviço de esqueleto demonstra cada um dos métodos de ciclo de vida:
public class ExampleService extends Service { int mStartMode; // indicates how to behave if the service is killed IBinder mBinder; // interface for clients that bind boolean mAllowRebind; // indicates whether onRebind should be used @Override public void {@link android.app.Service#onCreate onCreate}() { // The service is being created } @Override public int {@link android.app.Service#onStartCommand onStartCommand}(Intent intent, int flags, int startId) { // The service is starting, due to a call to {@link android.content.Context#startService startService()} return mStartMode; } @Override public IBinder {@link android.app.Service#onBind onBind}(Intent intent) { // A client is binding to the service with {@link android.content.Context#bindService bindService()} return mBinder; } @Override public boolean {@link android.app.Service#onUnbind onUnbind}(Intent intent) { // All clients have unbound with {@link android.content.Context#unbindService unbindService()} return mAllowRebind; } @Override public void {@link android.app.Service#onRebind onRebind}(Intent intent) { // A client is binding to the service with {@link android.content.Context#bindService bindService()}, // after onUnbind() has already been called } @Override public void {@link android.app.Service#onDestroy onDestroy}() { // The service is no longer used and is being destroyed } }
Observação: diferentemente dos métodos de retorno de chamada do ciclo de vida da atividade, você não precisa chamar a implementação da superclasse.
Ao implementar esses métodos, é possível monitorar dois retornos (loops) aninhados no ciclo de vida do serviço:
Os métodos {@link android.app.Service#onCreate onCreate()} e {@link android.app.Service#onDestroy onDestroy()} são chamados para todos os serviços, se tiverem sido criados por {@link android.content.Context#startService startService()} ou {@link android.content.Context#bindService bindService()}.
Se o serviço for iniciado, o ciclo de vida ativo terminará no mesmo momento em que o ciclo de vida inteiro terminar (o serviço permanece ativo mesmo após o retorno de {@link android.app.Service#onStartCommand onStartCommand()}). Se o serviço estiver vinculado, o ciclo de ida ativo acabará quando {@link android.app.Service#onUnbind onUnbind()} retornar.
Observação: apesar de um serviço iniciado ser interrompido com uma chamada de {@link android.app.Service#stopSelf stopSelf()} ou {@link android.content.Context#stopService stopService()}, não há um retorno de chamada respectivo para o serviço (não há retorno de chamada de {@code onStop()}). Portanto, a não ser que o serviço esteja vinculado a um cliente, o sistema o eliminará quando for interrompido — {@link android.app.Service#onDestroy onDestroy()} será o único retorno de chamada recebido.
A figura 2 ilustra os métodos de retorno de chamada tradicionais para um serviço. Apesar de a figura separar os serviços que são criados por {@link android.content.Context#startService startService()} daqueles que são criados por {@link android.content.Context#bindService bindService()}, observe que qualquer serviço, não importa como foi iniciado, pode permitir a vinculação de clientes. Portanto, um serviço que já foi iniciado com {@link android.app.Service#onStartCommand onStartCommand()} (por um cliente chamando {@link android.content.Context#startService startService()}) ainda pode receber uma chamada de {@link android.app.Service#onBind onBind()} (quando um cliente chama {@link android.content.Context#bindService bindService()}).
Para obter mais informações sobre como criar um serviço que forneça vinculação, consulte o documento Serviços vinculados, que aborda mais profundamente o método de retorno de chamada {@link android.app.Service#onRebind onRebind()} na seção sobre Gerenciamento do ciclo de vida de um serviço vinculado.