Pular para o conteúdo

Mais visitados

Visitados recentemente

navigation

Serviços

Um 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á se vincular a um serviço para interagir com ele e até estabelecer comunicação entre processos (IPC). Por exemplo, um serviço pode lidar com transaçõ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:

Iniciado
Um serviço é "iniciado" quando um componente do aplicativo (como um atividade) inicia-o chamando startService(). Quando iniciado, um serviço pode ficar em execução em segundo plano indefinidamente, mesmo que o componente que o iniciou seja destruído. Geralmente, um serviço iniciado realiza uma única operação e não retorna um resultado para o autor da chamada. Por exemplo, ele pode fazer download ou upload de um arquivo pela rede. Quando a operação for concluída, o serviço deverá ser interrompido.
Vinculado
Um serviço é "vinculado" quando um componente do aplicativo chama bindService() para vinculá-lo. Um serviço vinculado oferece uma interface servidor-cliente que permite que os componentes interajam com a interface, enviem solicitações, obtenham resultados, mesmo em processos com comunicação interprocessual (IPC). Um serviço vinculado permanece em execução somente 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 desfizerem o vínculo, o serviço será destruído.

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 onStartCommand() para permitir que os componentes iniciem o serviço e 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 Intent. No entanto, é possível declarar o serviço como privado, no arquivo do manifesto, e bloquear o acesso de outros aplicativos. Isso é 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.

Conceitos básicos

Para criar um serviço, você deve criar uma subclasse de Service (ou uma das subclasses existentes). Na implementação, será necessário modificar 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 modificar são:

onStartCommand()
O sistema chama esse método quando outro componente, como uma atividade, solicita que o serviço seja iniciado, chamando startService(). Quando esse método é executado, o serviço é iniciado e pode ser executado em segundo plano indefinidamente. Se implementar isso, é de sua responsabilidade interromper o serviço quando o trabalho for concluído, chamando stopSelf() ou stopService(). (caso queira somente fornecer a vinculação, não é necessário implementar esse método).
onBind()
O sistema chama esse método quando outro componente quer se vincular ao serviço (como para realizações de RPC) chamando bindService(). Na implementação desse método, você deve fornecer uma interface que os clientes usem para se comunicar com o serviço, retornando um IBinder. Você sempre deve implementar esse método, mas, se não quiser permitir a vinculação, retorne nulo.
onCreate()
O sistema chama esse método quando o serviço é criado pela primeira vez para realizar procedimentos únicos de configuração (antes de chamar onStartCommand() ou onBind()). Se o serviço já estiver em execução, esse método não é chamado.
onDestroy()
O sistema chama esse método quando o serviço não é mais usado e está sendo destruído. O serviço deve implementar isso para limpar quaisquer recursos, como encadeamentos, escutas registradas, receptores etc. 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 permanecerá em execução até ser interrompido por conta própria com stopSelf() ou por outro componente 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. 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 a 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), 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, você deverá programá-lo para lidar com reinicializações pelo sistema. Se o sistema eliminar seu serviço, ele reiniciará assim que os recursos estiverem disponíveis novamente (apesar de isso também depender do valor que você retornar de 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.

Declaração de serviço no manifesto

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 <service> como filho do elemento <application> . Por exemplo:

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

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

É possível incluir outros atributos no elemento <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 android:name é o único necessário — ele especifica o nome da classe do serviço. Ao publicar o aplicativo, não se deve alterar o nome dele porque, se isso acontecer, há riscos de ocorrência de erros de código devido à dependência de intents explícitos para iniciar ou vincular o serviço (leia a publicação do blog, Coisas que não podem mudar).

Para garantir a segurança do aplicativo, sempre use um intent explícito ao iniciar ou vincular Service e não declare filtros de intent para o serviço. Se for indispensável permitir alguma ambiguidade, como qual serviço deve ser usado para iniciar, é possível fornecer filtros de intents para os serviços e excluir o nome do componente de Intent, mas é preciso definir o pacote para o intent com setPackage(), que fornece desambiguação suficiente para o serviço-alvo.

Além disso, é possível garantir que o serviço esteja disponível somente para o aplicativo inclusive o atributo android:exported e definindo-o como "false". Isso impede efetivamente que outros aplicativos iniciem o serviço, mesmo usando um intent explícito.

Criação de um serviço iniciado

Um serviço iniciado é o que outro componente inicia chamando startService(), resultando em uma chamada para o método 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 seu trabalho for realizado, chamando stopSelf(). Outros componentes podem interrompê-lo chamando stopService().

Um componente do aplicativo, como uma atividade, pode iniciar o serviço chamando startService() e passando Intent, que especifica o serviço e inclui os dados para o serviço usar. O serviço recebe essa Intent no método 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 um intent para startService(). O serviço recebe o intent em onStartCommand(), conecta-se à internet e realiza a transação no banco de dados. Quando a transação é concluída, o serviço é interrompido e destruído.

Atenção: Por padrão, um serviço é executado no mesmo processo que o aplicativo em que ele é declarado e no encadeamento principal do aplicativo. 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:

Service
Essa é a classe de base para todos os serviços. Ao estender essa classe, é importante criar um novo encadeamento para fazer todo o trabalho do serviço, pois o serviço usa o encadeamento principal do aplicativo, por padrão, o que deve diminuir o desempenho de qualquer atividade que o aplicativo estiver executando.
IntentService
Essa é uma subclasse de Service que usa um encadeamento de trabalho para lidar com todas as solicitações de inicialização, uma por vez. Essa é a melhor opção se não quiser que o serviço lide com várias solicitações simultaneamente. Tudo o que você precisa fazer é implementar onHandleIntent(), que recebe o intent para cada solicitação de início para que você possa realizar o trabalho de segundo plano.

As seguintes seções descrevem como é possível implementar o serviço usando uma dessas classes.

Extensão da classe IntentService

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

O IntentService faz o seguinte:

Tudo isso se soma ao fato de que basta implementar onHandleIntent() para fazer o trabalho fornecido pelo cliente. (embora também seja necessário fornecer um pequeno construtor para o serviço).

Eis um exemplo de implementação de IntentService:

public class HelloIntentService extends IntentService {

  /**
   * A constructor is required, and must call the super IntentService(String)
   * 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.
      try {
          Thread.sleep(5000);
      } catch (InterruptedException e) {
          // Restore interrupt status.
          Thread.currentThread().interrupt();
      }
  }
}

É tudo de que você precisa: um construtor e uma implementação de onHandleIntent().

Se você decidir modificar outros métodos de retorno de chamada, como onCreate(), onStartCommand() ou onDestroy(), certifique-se de chamar a superimplementação para que o IntentService lide adequadamente com a vida útil do encadeamento de trabalho.

Por exemplo, onStartCommand() deve retornar a implementação padrão (que é como o intent é entregue para 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 onHandleIntent(), o único método que não precisa ser usado para chamar a superclasse é 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 Service, que tem muito mais códigos, mas que pode ser apropriada para lidar com solicitações de inicialização simultâneas.

Extensão da classe Service

Como você viu na seção anterior, o uso de 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 Service para lidar com cada intent.

Para efeito de comparação, o exemplo de código a seguir é uma implementação da classe Service que realiza exatamente o mesmo trabalho que o exemplo acima usando 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.
          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 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 IntentService.

No entanto, como você lida com cada chamada de onStartCommand(), é possível realizar várias solicitações simultaneamente. Isso não é o que esse 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 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 foi discutido acima, a implementação padrão de IntentService lida com isso, apesar de ser possível modificá-la). O valor de retorno de onStartCommand() deve ser uma das seguintes constantes:

START_NOT_STICKY
Se o sistema eliminar o serviço após o retorno de onStartCommand(), não recrie o serviço, a não ser que tenha intents pendentes para entregar. Essa é a opção mais segura para evitar executar o serviço quando desnecessário e quando o aplicativo puder simplesmente reiniciar qualquer trabalho incompleto.
START_STICKY
Se o sistema eliminar o serviço após o retorno de onStartCommand(), recrie o serviço e chame onStartCommand(), mas não reentregue o último intent. Em vez disso, o sistema chama onStartCommand() com intent nulo, a não ser que tenha intents pendentes para iniciar o serviço e, nesse caso, esses intents são entregues. Isso é adequado para reprodutores de mídia (ou serviços semelhantes) que não estejam executando comandos, mas estejam em execução indefinidamente e aguardando um trabalho.
START_REDELIVER_INTENT
Se o sistema eliminar o serviço após o retorno de onStartCommand(), recrie o serviço e chame onStartCommand() com o último intent entregue ao serviço. Quaisquer intents pendentes são entregues uma de cada vez. Isso é adequado para serviços que estejam realizando um trabalho ativamente que deva ser retomado imediatamente, como o download de um arquivo.

Para obter mais informações sobre esses valores de retorno, veja a documentação de referência vinculada a cada constante.

Início de um serviço

É possível iniciar um dispositivo de uma atividade ou outro componente do aplicativo passando uma Intent a startService(). O sistema Android chama o método onStartCommand() do serviço e passa-lhe a Intent. (nunca se deve chamar onStartCommand() diretamente).

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

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

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

Se o serviço não fornecer vinculação, o intent entregue com startService() será 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 PendingIntent para uma transmissão (com getBroadcast()) e entregá-la ao serviço na 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 onStartCommand() do serviço. No entanto, somente uma solicitação para interromper o serviço (com stopSelf() ou stopService()) é necessária para interrompê-lo.

Interrupção de um serviço

Um serviço iniciado deve gerenciar o 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 onStartCommand() retornar. Portanto, o serviço deve ser interrompido chamando stopSelf() ou outro componente pode interrompê-lo chamando stopService().

Ao solicitar a interrupção com stopSelf() ou stopService(), o sistema elimina o serviço assim que possível.

No entanto, se o serviço lida com várias solicitações para 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 esse problema, é possível usar 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 stopSelf(int), você passa o código da solicitação de inicialização (o startId entregue a onStartCommand()) para aquele ao qual 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 código 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 chamar stopService() para interromper o serviço. Mesmo se for possível se vincular ao serviço, deve-se sempre interrompê-lo por conta própria se ele tiver recebido uma chamada de 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.

Criação de um serviço vinculado

Serviços vinculados permitem que componentes de aplicativo sejam vinculados chamando bindService() para criar uma conexão de longo prazo (e, geralmente, não permite que os componentes os iniciem chamando 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, deve-se implementar o método de retorno de chamada onBind() para retornar um IBinder que defina a interface de comunicação com o serviço. Outros componentes de aplicativo podem chamar bindService() para recuperar a interface e começar a chamar métodos no serviço. O serviço existe 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 onStartCommand()).

Para criar um serviço vinculado, a primeira coisa a se fazer é definir a interface que especifica como um cliente pode se comunicar com o servidor. Essa interface entre o serviço e um cliente deve ser uma implementação de IBinder e é o que o serviço deve retornar do método de retorno de chamada onBind(). Quando o cliente receber IBinder, ele poderá começar a interagir com o serviço por meio da interface.

Vários clientes podem se vincular ao serviço por vez. Quando um cliente terminar de interagir com o serviço, ele chamará 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 que um serviço iniciado. Logo, a discussão sobre serviços vinculados aparece em um documento separado sobre Serviços vinculados.

Envio de notificações ao usuário

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 sobre dele. Quando o usuário seleciona a notificação a partir da exibição expandida, ela pode iniciar uma atividade (como a exibição do arquivo baixado).

Consulte os guias de desenvolvedor Notificações de aviso ou Notificações da barra de status para obter mais informações.

Execução de serviço em primeiro plano

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 a execução do serviço em primeiro plano, chame startForeground(). Esse método usa dois parâmetros: um número inteiro que identifica de forma exclusiva a notificação e 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 código de número inteiro fornecido para startForeground() não deve ser 0.

Para remover o serviço do primeiro plano, chame stopForeground(). Esse método usa um booleano, indicando se deve remover também a notificação da barra de status. Esse 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.

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 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:

Esses dois caminhos não são inteiramente separados. Ou seja, é possível vincular um serviço que já foi iniciado com startService(). Por exemplo, um serviço de música de segundo plano pode ser iniciado chamando startService() com uma 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 chamar bindService() para vincular-se ao serviço. Em casos como esse, nem stopService() nem stopSelf() interrompe o serviço até todos os clientes se desvincularem.

Implementação dos retornos de chamada do ciclo de vida

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 serviço básico a seguir 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 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 mStartMode;
    }
    @Override
    public IBinder onBind(Intent intent) {
        // A client is binding to the service with bindService()
        return mBinder;
    }
    @Override
    public boolean onUnbind(Intent intent) {
        // All clients have unbound with unbindService()
        return mAllowRebind;
    }
    @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: Diferentemente dos métodos de retorno de chamada do ciclo de vida da atividade, você não precisa chamar a implementação da superclasse.

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().

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

Observação: Apesar de um serviço iniciado ser interrompido com uma chamada de stopSelf() ou stopService(), não haverá nenhum retorno de chamada respectivo para o serviço (não há retorno de chamada de onStop()). Portanto, a não ser que o serviço esteja vinculado a um cliente, o sistema o eliminará quando for interrompido — 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 startService() daqueles que são criados por 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 onStartCommand() (por um cliente chamando startService()) ainda pode receber uma chamada de onBind() (quando um cliente chama 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 onRebind() na seção sobre Gerenciamento do ciclo de vida de um serviço vinculado.

Este site usa cookies para armazenar suas preferências quanto às opções de idioma e exibição específicas ao site.

Receba as dicas e notícias mais recentes para desenvolvedores Android que ajudarão você a ter sucesso no Google Play.

* Campos obrigatórios

Uhu!

Siga o Google Developers no WeChat

Navegar neste site em ?

Você solicitou uma página em , mas sua preferência de idioma para este site está definida como .

Quer alterar sua preferência de idioma e navegar neste site em ? Para alterar a preferência de idioma depois, use o menu de idiomas na parte inferior de cada página.

É preciso ter o nível de API ou superior para esta aula

Este documento está oculto porque o nível de API selecionado para a documentação é o . Para alterar o nível, clique no seletor acima da barra de navegação esquerda.

Para mais informações sobre como especificar o nível de API que o seu app precisa, leia o artigo Compatibilidade com diferentes versões de plataforma.

Take a short survey?
Help us improve the Android developer experience. (April 2018 — Developer Survey)