Visão geral dos serviços

Um Service é um componente de aplicativo capaz de executar operações de longa duração em segundo plano. Ele não fornece uma interface do usuário. Depois de iniciado, um serviço pode continuar em execução por algum tempo, mesmo depois que o usuário alterna para outro aplicativo. Além disso, um componente pode se vincular a um serviço para interagir com ele e até estabelecer comunicação entre processos (IPC). Por exemplo, um serviço pode processar transações de rede, tocar música, executar E/S de arquivos ou interagir com um provedor de conteúdo, tudo em segundo plano.

Cuidado:um serviço é executado na linha de execução principal do processo de hospedagem. O serviço não cria a própria linha de execução e não é executado em um processo separado, a menos que você especifique o contrário. Execute qualquer operação de bloqueio em uma linha de execução separada no serviço para evitar erros "O app não está respondendo" (ANR).

Tipos de serviços

Veja os três tipos diferentes de serviços:

Primeiro plano

Um serviço em primeiro plano executa alguma operação perceptível pelo usuário. Por exemplo, um app de áudio usaria um serviço em primeiro plano para tocar uma faixa de áudio. Os serviços em primeiro plano precisam exibir uma Notificação. Os serviços em primeiro plano continuam em execução mesmo quando o usuário não está interagindo com o app.

Ao usar um serviço em primeiro plano, é necessário mostrar uma notificação para que os usuários estejam ativamente cientes de que o serviço está em execução. Essa notificação não pode ser dispensada, a menos que o serviço seja interrompido ou removido do primeiro plano.

Saiba mais sobre como configurar serviços em primeiro plano no seu app.

Observação: a API WorkManager oferece uma maneira flexível de agendar tarefas e pode executar esses jobs como serviços em primeiro plano, se necessário. Em muitos casos, é preferível usar o WorkManager do que usar os serviços em primeiro plano diretamente.

Contexto
Um serviço em segundo plano executa uma operação que não é diretamente percebida pelo usuário. Por exemplo, se um app usasse um serviço para compactar o armazenamento, isso geralmente seria um serviço em segundo plano.

Observação:se o app for direcionado ao nível 26 da API ou a versões mais recentes, o sistema vai impor restrições na execução de serviços em segundo plano quando o app não estiver em primeiro plano. Na maioria das situações, por exemplo, não é recomendado acessar informações de local em segundo plano. Em vez disso, agende tarefas usando o WorkManager.

Vinculado
Um serviço é vinculado quando um componente do aplicativo é vinculado a ele chamando bindService(). Um serviço vinculado oferece uma interface cliente-servidor que permite que os componentes interajam com o serviço, enviem solicitações, recebam resultados e até façam isso em vários processos com comunicação entre processos (IPC). Um serviço vinculado só será executado enquanto outro componente do aplicativo estiver vinculado a ele. Vários componentes podem ser vinculados ao serviço de uma só vez, mas quando todos eles forem desvinculados, o serviço será destruído.

Embora esta documentação geralmente discuta os serviços iniciados e vinculados separadamente, seu serviço pode funcionar de duas maneiras: ele pode ser iniciado (para ser executado indefinidamente) e também permitir vinculação. Basta implementar alguns métodos de callback: onStartCommand() para permitir que os componentes o iniciem e onBind() para permitir a vinculação.

Independentemente de o serviço ser iniciado, vinculado ou ambos, qualquer componente do aplicativo pode usar o serviço, mesmo de um aplicativo separado, da mesma forma que qualquer componente pode usar uma atividade, iniciando com uma Intent. No entanto, você pode declarar o serviço como privado no arquivo de manifesto e bloquear o acesso de outros aplicativos. Isso é discutido com mais detalhes na seção sobre Como declarar o serviço no manifesto.

Como escolher entre um serviço e um thread

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, crie um serviço somente se for necessário.

Se for necessário executar o trabalho fora da linha de execução principal, mas somente enquanto o usuário estiver interagindo com o aplicativo, crie uma nova linha de execução no contexto de outro componente do aplicativo. Por exemplo, se você quiser tocar uma música, mas apenas enquanto sua atividade estiver em execução, poderá criar uma linha de execução em onCreate(), começar a executá-la em onStart() e interrompê-la em onStop(). Considere também usar pools de linhas de execução e executores do pacote java.util.concurrent ou de corrotinas de Kotlin em vez da classe Thread tradicional. Consulte o documento Linhas de execução no Android para mais informações sobre como mover a execução para linhas de execução em segundo plano.

Lembre-se de que, se você usar um serviço, ele ainda será executado na linha de execução principal do aplicativo por padrão. Portanto, ainda será necessário criar uma nova linha de execução no serviço se ele realizar operações intensivas ou de bloqueio.

Noções básicas

Para criar um serviço, é necessário criar uma subclasse de Service ou usar uma das subclasses já existentes. Na implementação, é necessário substituir alguns métodos de callback que processam aspectos importantes do ciclo de vida do serviço e fornecer um mecanismo que permita que os componentes sejam vinculados ao serviço, se apropriado. Estes são os métodos de callback mais importantes que precisam ser substituídos:

onStartCommand()
O sistema invoca esse método chamando startService() quando outro componente (como uma atividade) solicita que o serviço seja iniciado. Quando esse método é executado, o serviço é iniciado e pode ser executado em segundo plano indefinidamente. Se você implementar isso, é sua responsabilidade interromper o serviço quando o trabalho for concluído, chamando stopSelf() ou stopService(). Se você quiser apenas fornecer a vinculação, não será necessário implementar esse método.
onBind()
O sistema invoca esse método chamando bindService() quando outro componente quer se vincular ao serviço (como para executar a RPC). Na implementação desse método, é necessário fornecer uma interface que os clientes usem para se comunicar com o serviço, retornando um IBinder. Você precisa sempre implementar esse método. No entanto, se não quiser permitir a vinculação, retorne nulo.
onCreate()
O sistema invoca esse método para executar procedimentos únicos de configuração quando o serviço é criado inicialmente (antes de chamar onStartCommand() ou onBind()). Se o serviço já estiver em execução, esse método não será chamado.
onDestroy()
O sistema invoca esse método quando o serviço não é mais usado e está sendo destruído. Seu serviço precisa implementar isso para limpar todos os recursos, como linhas de execução, listeners registrados ou receptores. Essa é a última chamada que o serviço recebe.

Se um componente iniciar o serviço chamando startService() (o que resulta em uma chamada para onStartCommand()), o serviço continuará em execução até ser interrompido com stopSelf() ou até que outro componente o interrompa chamando stopService().

Se um componente chamar bindService() para criar o serviço e onStartCommand() não for chamado, o serviço será executado somente enquanto o componente estiver vinculado a ele. Depois que o serviço é desvinculado de todos os clientes, o sistema o destruirá.

O sistema Android interrompe um serviço somente quando a memória está baixa e precisa recuperar recursos do sistema para a atividade com o foco do usuário. Se o serviço estiver vinculado a uma atividade com foco do usuário, é menos provável que ele seja encerrado. Se o serviço for declarado como executado em primeiro plano, ele raramente será eliminado. Se o serviço for iniciado e for de longa duração, o sistema diminuirá a posição dele na lista de tarefas em segundo plano ao longo do tempo e o serviço ficará altamente suscetível a encerramento. Se o serviço for iniciado, ele precisará ser projetado para lidar com as reinicializações pelo sistema. Se o sistema eliminar seu serviço, ele reiniciará assim que os recursos ficarem disponíveis, mas isso também depende do valor retornado de onStartCommand(). Para mais informações sobre quando o sistema pode destruir um serviço, consulte o documento Processos e linhas de execução.

Nas seções a seguir, você verá como criar os métodos de serviço startService() e bindService() e como usá-los em outros componentes do aplicativo.

Declaração de serviço no manifesto

Declare todos os serviços no arquivo de manifesto do seu aplicativo, assim como você faz para atividades e outros componentes.

Para declarar o serviço, adicione um elemento <service> como filho do elemento <application>. Confira um exemplo:

<manifest ... >
  ...
  <application ... >
      <service android:name=".ExampleService" />
      ...
  </application>
</manifest>

Consulte a referência do elemento <service> para mais informações sobre como declarar o serviço no manifesto.

Há outros atributos que você pode incluir no elemento <service> para definir propriedades, como as permissões necessárias para iniciar o serviço e o processo em que o serviço precisa ser executado. O atributo android:name é o único obrigatório, porque especifica o nome da classe do serviço. Depois de publicar o aplicativo, deixe o nome inalterado para evitar o risco de corromper o código devido à dependência de intents explícitas para iniciar ou vincular o serviço (leia a postagem do blog Coisas que não podem mudar).

Cuidado: para garantir a segurança do app, sempre use uma intent explícita ao iniciar uma Service e não declare filtros de intent para seus serviços. O uso de uma intent implícita para iniciar um serviço representa um risco de segurança, porque não é possível saber qual serviço responde à intent, e o usuário não pode ver qual serviço é iniciado. No Android 5.0 (nível 21 da API) e versões mais recentes, o sistema gera uma exceção quando bindService() é chamado com uma intent implícita.

Para garantir que o serviço esteja disponível apenas para o app, inclua o atributo android:exported e o defina como false. Isso impede que outros apps iniciem seu serviço, mesmo usando uma intent explícita.

Observação: os usuários podem ver quais serviços estão em execução no dispositivo. Se ele vir um serviço que não reconhece ou não confia, ele pode interrompê-lo. Para evitar que o serviço seja interrompido acidentalmente pelos usuários, é necessário adicionar o atributo android:description ao elemento <service> no manifesto do app. Na descrição, explique em poucas palavras o que o serviço faz e os benefícios que ele oferece.

Criação de um serviço iniciado

Um serviço iniciado é aquele que outro componente inicia chamando startService(), o que resulta em uma chamada para o método onStartCommand() do serviço.

Quando um serviço é iniciado, ele tem um ciclo de vida independente do componente que o iniciou. O serviço pode ser executado em segundo plano indefinidamente, mesmo que o componente que o iniciou seja destruído. Assim, o serviço será interrompido quando o job for concluído, chamando stopSelf(). Caso contrário, outro componente poderá interrompê-lo chamando stopService().

Um componente de aplicativo, como uma atividade, pode iniciar o serviço chamando startService() e transmitindo um Intent que especifica o serviço e inclui todos os dados para o serviço usar. O serviço recebe esse Intent no método onStartCommand().

Por exemplo, imagine que uma atividade precise salvar alguns dados em um banco de dados on-line. A atividade pode iniciar um serviço complementar e entregar a ele os dados a serem salvos transmitindo uma intent para startService(). O serviço recebe a intent em onStartCommand(), se conecta à Internet e executa a transação do banco de dados. Quando a transação é concluída, o serviço é interrompido e destruído.

Cuidado:um serviço é executado no mesmo processo que o aplicativo em que é declarado e na linha de execução principal do aplicativo por padrão. Se o serviço realizar operações intensivas ou de bloqueio enquanto o usuário interage com uma atividade do mesmo aplicativo, o serviço vai diminuir o desempenho da atividade. Para evitar impacto no desempenho do aplicativo, inicie uma nova linha de execução dentro do serviço.

A classe Service é a classe base de todos os serviços. Ao estender essa classe, é importante criar uma nova linha de execução em que o serviço possa concluir todo o trabalho. O serviço usa a linha de execução principal do aplicativo por padrão, o que pode retardar o desempenho de qualquer atividade que o aplicativo esteja executando.

O framework do Android também fornece a subclasse IntentService de Service, que usa uma linha de execução de worker para processar todas as solicitações de inicialização, uma de cada vez. O uso dessa classe não é recomendado para novos apps, já que não funcionará bem a partir do Android 8 Oreo devido à introdução dos limites de execução em segundo plano. Além disso, o uso dela foi suspenso a partir do Android 11. Você pode usar JobIntentService como substituição de IntentService, que é compatível com versões mais recentes do Android.

As seções a seguir descrevem como implementar seu próprio serviço personalizado. No entanto, é importante usar o WorkManager na maioria dos casos de uso. Consulte o guia para processamento em segundo plano no Android para ver se há uma solução que atenda às suas necessidades.

Extensão da classe Service

Você pode estender a classe Service para processar cada intent recebida. Veja como pode ser uma implementação básica:

Kotlin

class HelloService : Service() {

    private var serviceLooper: Looper? = null
    private var serviceHandler: ServiceHandler? = null

    // Handler that receives messages from the thread
    private inner class ServiceHandler(looper: Looper) : Handler(looper) {

        override fun handleMessage(msg: Message) {
            // Normally we would do some work here, like download a file.
            // For our sample, we just sleep for 5 seconds.
            try {
                Thread.sleep(5000)
            } catch (e: InterruptedException) {
                // Restore interrupt status.
                Thread.currentThread().interrupt()
            }

            // Stop the service using the startId, so that we don't stop
            // the service in the middle of handling another job
            stopSelf(msg.arg1)
        }
    }

    override fun 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("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND).apply {
            start()

            // Get the HandlerThread's Looper and use it for our Handler
            serviceLooper = looper
            serviceHandler = ServiceHandler(looper)
        }
    }

    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
        Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show()

        // For each start request, 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
        serviceHandler?.obtainMessage()?.also { msg ->
            msg.arg1 = startId
            serviceHandler?.sendMessage(msg)
        }

        // If we get killed, after returning from here, restart
        return START_STICKY
    }

    override fun onBind(intent: Intent): IBinder? {
        // We don't provide binding, so return null
        return null
    }

    override fun onDestroy() {
        Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show()
    }
}

Java

public class HelloService extends Service {
  private Looper serviceLooper;
  private ServiceHandler serviceHandler;

  // 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.
          try {
              Thread.sleep(5000);
          } catch (InterruptedException e) {
              // Restore interrupt status.
              Thread.currentThread().interrupt();
          }
          // 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 doesn't 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
    serviceLooper = thread.getLooper();
    serviceHandler = new ServiceHandler(serviceLooper);
  }

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
      Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();

      // For each 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 = serviceHandler.obtainMessage();
      msg.arg1 = startId;
      serviceHandler.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();
  }
}

O código de exemplo processa todas as chamadas recebidas em onStartCommand() e publica o trabalho em um Handler executado em uma linha de execução em segundo plano. Ele funciona como um IntentService e processa todas as solicitações em série, uma após a outra. Você pode alterar o código para executar o trabalho em um pool de linhas de execução, por exemplo, se quiser executar várias solicitações simultaneamente.

Observe que o método onStartCommand() precisa retornar um número inteiro. O número inteiro é um valor que descreve como o sistema vai continuar o serviço caso o sistema o elimine. O valor de retorno de onStartCommand() precisa ser uma das constantes abaixo:

START_NOT_STICKY
Se o sistema eliminar o serviço depois que onStartCommand() retornar, não recrie o serviço, a menos que haja intents pendentes para entregar. Essa é a opção mais segura para evitar a execução do serviço quando desnecessário e quando o aplicativo puder simplesmente reiniciar todos os jobs inacabados.
START_STICKY
Se o sistema eliminar o serviço depois que onStartCommand() retornar, recrie o serviço e chame onStartCommand(), mas não entregue novamente a última intent. Em vez disso, o sistema chamará onStartCommand() com uma intent nula, a menos que haja intents pendentes para iniciar o serviço. Nesse caso, essas intents são entregues. Isso é adequado para players de mídia (ou serviços semelhantes) que não executam comandos, mas estão em execução indefinidamente e aguardando um job.
START_REDELIVER_INTENT
Se o sistema eliminar o serviço depois que onStartCommand() retornar, recrie o serviço e chame onStartCommand() com a última intent entregue ao serviço. Quaisquer intents pendentes são entregues um de cada vez. Isso é adequado para serviços que estão realizando ativamente um job que precisa ser retomado imediatamente, como o download de um arquivo.

Para mais detalhes sobre esses valores de retorno, consulte a documentação de referência vinculada para cada constante.

Iniciar um serviço

Transmita um Intent para startService() ou startForegroundService() para iniciar um serviço a partir de uma atividade ou outro componente de aplicativo. O sistema Android chama o método onStartCommand() do serviço e transmite a ele o Intent, que especifica qual serviço iniciar.

Observação: se o app for direcionado ao nível 26 da API ou mais recente, o sistema impõe restrições ao uso ou à criação de serviços em segundo plano, a menos que o próprio app esteja em primeiro plano. Se um app precisar criar um serviço em primeiro plano, ele precisará chamar startForegroundService(). Esse método cria um serviço em segundo plano, mas sinaliza ao sistema que o serviço será promovido ao primeiro plano. Depois que o serviço é criado, o serviço precisa chamar o método startForeground() em até cinco segundos.

Por exemplo, uma atividade pode iniciar o serviço de exemplo na seção anterior (HelloService) usando uma intent explícita com startService(), como mostrado aqui:

Kotlin

startService(Intent(this, HelloService::class.java))

Java

startService(new Intent(this, HelloService.class));

O método startService() é retornado imediatamente, e o sistema Android chama o método onStartCommand() do serviço. Se o serviço ainda não estiver em execução, o sistema primeiro chamará onCreate() e, em seguida, onStartCommand().

Se o serviço não fornecer vinculação, a intent entregue com startService() será o único modo de comunicação entre o componente do aplicativo e o serviço. No entanto, se você quiser que o serviço envie um resultado, o cliente que inicia o serviço pode criar um PendingIntent para uma transmissão (com getBroadcast()) e entregá-lo ao serviço na Intent que o inicia. O serviço pode usar a transmissão para entregar um resultado.

Várias solicitações para iniciar o serviço resultam em várias chamadas correspondentes ao onStartCommand() do serviço. No entanto, apenas uma solicitação para interromper o serviço (com stopSelf() ou stopService()) é necessária para interrompê-lo.

Interromper um serviço

Um serviço iniciado precisa gerenciar o próprio ciclo de vida. Ou seja, o sistema não interrompe nem destrói o serviço, a menos que precise recuperar a memória do sistema e o serviço continuar em execução após o retorno de onStartCommand(). O serviço precisa ser interrompido chamando stopSelf(). Caso contrário, outro componente pode interrompê-lo chamando stopService().

Quando a interrupção com stopSelf() ou stopService() é solicitada, o sistema elimina o serviço o mais rápido possível.

Se o serviço processar várias solicitações para onStartCommand() ao mesmo tempo, não interrompa o serviço ao terminar de processar uma solicitação de início, porque talvez você tenha recebido uma nova solicitação de inicialização (encerrar no final da primeira solicitação encerraria a segunda). Para evitar esse problema, use stopSelf(int) para garantir que sua solicitação de interrupção do serviço seja sempre baseada na solicitação de inicialização mais recente. Ou seja, ao chamar stopSelf(int), você transmite o ID da solicitação de inicialização (o startId entregue a onStartCommand()) a que a solicitação de interrupção corresponde. Em seguida, se o serviço receber uma nova solicitação de inicialização antes de ser possível chamar stopSelf(int), o ID não vai corresponder, e o serviço não vai ser interrompido.

Cuidado:para evitar o desperdício de recursos do sistema e o consumo da bateria, certifique-se de que seu aplicativo interrompa os serviços quando terminar o trabalho. Se necessário, outros componentes podem interromper o serviço chamando stopService(). Mesmo que você ative a vinculação do serviço, sempre precisará interrompê-lo por conta própria se ele receber uma chamada para onStartCommand().

Para 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.

Como criar um serviço vinculado

Um serviço vinculado permite que componentes de aplicativo sejam vinculados chamando bindService() para criar uma conexão de longo prazo. Geralmente, ela não permite que os componentes a iniciem chamando startService().

Crie um serviço vinculado quando quiser interagir com o serviço a partir de atividades e outros componentes no aplicativo ou para expor algumas das funcionalidades do aplicativo a outros aplicativos por meio da comunicação entre processos (IPC).

Para criar um serviço vinculado, implemente o método de callback onBind() para retornar um IBinder que define a interface de comunicação com o serviço. Outros componentes de aplicativo podem chamar bindService() para extrair a interface e começar a chamar métodos no serviço. O serviço existe apenas para disponibilizar o componente do aplicativo que está vinculado a ele. Portanto, quando não há componentes vinculados ao serviço, o sistema o destrói. Não é necessário interromper um serviço vinculado da mesma maneira que é feito quando o serviço é iniciado pelo onStartCommand().

Para criar um serviço vinculado, defina a interface que especifica como um cliente pode se comunicar com o serviço. Essa interface entre o serviço e um cliente precisa ser uma implementação de IBinder e é o que seu serviço precisa retornar do método de callback onBind(). Depois que o cliente receber o IBinder, ele poderá começar a interagir com o serviço por meio dessa interface.

Vários clientes podem se vincular ao serviço por vez. Quando um cliente termina de interagir com o serviço, ele chama unbindService() para se desvincular. 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 do que um serviço iniciado. Por esses motivos, a discussão sobre serviços vinculados aparece em um documento separado sobre Serviços vinculados.

Envio de notificações ao usuário

Quando um serviço está em execução, ele pode notificar o usuário sobre eventos usando notificações da snackbar ou notificações da barra de status.

Uma notificação de snackbar é uma mensagem que aparece na superfície da janela atual por apenas um momento antes de desaparecer. 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).

Normalmente, uma notificação da barra de status é a melhor técnica a ser usada quando um trabalho em segundo plano, como um download de arquivo, foi concluído, e o usuário agora pode realizar ações. Quando o usuário seleciona a notificação na visualização expandida, ela pode iniciar uma atividade, como para exibir o arquivo transferido por download.

Gerenciamento do ciclo de vida de um serviço

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 destruído, porque um serviço pode ser executado em segundo plano sem que o usuário esteja ciente.

O ciclo de vida do serviço, desde quando ele é criado até ser destruído, pode seguir um destes dois caminhos:

  • Um serviço iniciado

    O serviço é criado quando outro componente chama startService(). O serviço é executado indefinidamente e precisa ser interrompido chamando stopSelf(). Outro componente também pode interromper o serviço chamando stopService(). Quando o serviço é interrompido, o sistema o elimina.

  • Um serviço vinculado

    O serviço é criado quando outro componente (um cliente) chama bindService(). Em seguida, o cliente se comunica com o serviço por uma interface IBinder. O cliente pode encerrar a conexão chamando unbindService(). Vários clientes podem se vincular ao mesmo serviço e, quando todos se desvinculam, o sistema destrói o serviço. O serviço não precisa ser interrompido.

Esses dois caminhos não são totalmente separados. É possível se vincular a um serviço que já tenha sido iniciado com startService(). Por exemplo, é possível iniciar um serviço de música em segundo plano chamando startService() com um Intent que identifique a música a ser tocada. Depois, possivelmente quando o usuário quiser exercer mais controle sobre o player ou receber informações sobre a música atual, uma atividade poderá se vincular ao serviço chamando bindService(). Nesses casos, stopService() ou stopSelf() não interrompem o serviço até que todos os clientes sejam desvinculados.

Implementação dos callbacks do ciclo de vida

Como uma atividade, um serviço tem métodos de callback do ciclo de vida que podem ser implementados para monitorar mudanças no estado do serviço e realizar trabalhos em momentos adequados. O serviço básico a seguir demonstra cada um dos métodos de ciclo de vida:

Kotlin

class ExampleService : Service() {
    private var startMode: Int = 0             // indicates how to behave if the service is killed
    private var binder: IBinder? = null        // interface for clients that bind
    private var allowRebind: Boolean = false   // indicates whether onRebind should be used

    override fun onCreate() {
        // The service is being created
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        // The service is starting, due to a call to startService()
        return startMode
    }

    override fun onBind(intent: Intent): IBinder? {
        // A client is binding to the service with bindService()
        return binder
    }

    override fun onUnbind(intent: Intent): Boolean {
        // All clients have unbound with unbindService()
        return allowRebind
    }

    override fun onRebind(intent: Intent) {
        // A client is binding to the service with bindService(),
        // after onUnbind() has already been called
    }

    override fun onDestroy() {
        // The service is no longer used and is being destroyed
    }
}

Java

public class ExampleService extends Service {
    int startMode;       // indicates how to behave if the service is killed
    IBinder binder;      // interface for clients that bind
    boolean allowRebind; // indicates whether onRebind should be used

    @Override
    public void onCreate() {
        // The service is being created
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // The service is starting, due to a call to startService()
        return startMode;
    }
    @Override
    public IBinder onBind(Intent intent) {
        // A client is binding to the service with bindService()
        return binder;
    }
    @Override
    public boolean onUnbind(Intent intent) {
        // All clients have unbound with unbindService()
        return allowRebind;
    }
    @Override
    public void onRebind(Intent intent) {
        // A client is binding to the service with bindService(),
        // after onUnbind() has already been called
    }
    @Override
    public void onDestroy() {
        // The service is no longer used and is being destroyed
    }
}

Observação:ao contrário dos métodos de callback do ciclo de vida da atividade, você não precisa chamar a implementação da superclasse desses métodos de callback.

Figura 2. Ciclo de vida do serviço. O diagrama à esquerda mostra o ciclo de vida quando o serviço é criado com startService(), e o diagrama à direita mostra o ciclo de vida quando o serviço é criado com bindService().

A figura 2 ilustra os métodos de callback tradicionais para um serviço. Embora a figura separa os serviços criados por startService() daqueles criados por bindService(), qualquer serviço, independente de como foi iniciado, pode permitir que os clientes se vinculem a ele. Um serviço que foi iniciado inicialmente com onStartCommand() (por um cliente chamando startService()) ainda pode receber uma chamada para onBind() (quando um cliente chama bindService()).

Ao implementar esses métodos, é possível monitorar esses dois loops aninhados do ciclo de vida do serviço:

  • O ciclo de vida inteiro de um serviço ocorre entre o momento em que onCreate() é chamado e o momento em que onDestroy() retorna. Como uma atividade, um serviço faz a configuração inicial em onCreate() e libera todos os recursos restantes em onDestroy(). Por exemplo, um serviço de reprodução de música pode criar a linha de execução em que a música é tocada em onCreate() e, em seguida, interromper a linha de execução em onDestroy().

    Observação: os métodos onCreate() e onDestroy() são chamados para todos os serviços, sejam criados por startService() ou bindService().

  • O ciclo de vida ativo de um serviço começa com uma chamada para onStartCommand() ou onBind(). Cada método recebe o Intent que foi transmitido para startService() ou bindService().

    Se o serviço for iniciado, o ciclo de vida ativo terminará ao mesmo tempo em que o ciclo de vida inteiro terminar. O serviço continuará ativo mesmo após o retorno de onStartCommand(). Se o serviço estiver vinculado, a vida útil ativa terminará quando onUnbind() retornar.

Observação:embora um serviço iniciado seja interrompido por uma chamada para stopSelf() ou stopService(), não há um callback respectivo para o serviço (não há um callback onStop()). A menos que o serviço esteja vinculado a um cliente, o sistema o destruirá quando o serviço for interrompido. onDestroy() é o único callback recebido.

Para mais informações sobre como criar um serviço que fornece vinculação, consulte o documento Serviços vinculados, que inclui mais informações sobre o método de callback onRebind() na seção sobre Como gerenciar o ciclo de vida de um serviço vinculado.