Caso prefira, você encontrará todo esse material, em inglês, no site do Developer Android. A tradução e comentários dos materiais eu faço livremente para ajudar a comunidade que fala português.

quarta-feira, 6 de abril de 2011

Services - Parte 01

Um serviço é um componente da aplicação que pode realizar operações de longa duração em modo background e não prove interface de usuário. Outro componente de aplicação pode iniciar o serviço e ele vai continuar rodando no background mesmo que o usuário mude para outra aplicação. Adicionalmente, um componente pode fazer o bind para um serviço para interagir com ele e inclusive realizar processos de comunicação entre processo (IPC na sigla em inglês que significa Inter-Process communication). Por exemplo, um serviço pode querer manusear transações de rede, tocar música, fazer uma troca de arquivo (processo de I/O) ou interagir com um content provider, tudo em modo background.

Um serviço essencialmente tem duas formas:

Started
Um serviço está iniciado quando um componente de aplicação (como uma atividade) inicia-o chamando startService(). Uma vez iniciado, o serviço pode rodar em modo background indefinidamente, mesmo que o componente que o iniciou seja destruído. Usualmente, um serviço iniciado realiza uma tarefa única e não retorna o resultado para quem o chamou. Por exemplo, você pode fazer o download ou upload de arquivos em uma rede. Quando a operação for terminada, o serviço termina sem a necessidade de interação do usuário.

Bound
Um serviço está bound quando um componente de aplicação faz um bind para ele chamando bindService(). Um serviço bound oferece uma interface cliente servidor que permite ao componente interagir com o serviço, enviar requisições, obter resulados e mesmo fazer alguns processos com comunicação entre processos (IPC). Um serviço bound roda apenas enquanto o componente da aplicação estiver ligado a ele. Multiplos componentes podem ser ligados a um serviço ao mesmo tempo mas quando todos eles se desligarem dele, o serviço será destruído.

Apesar dessa documentação geralmente discutir esses dois tipos de serviço separadamente, seu serviço pode trabalhar das duas formas - ele pode ser inicializado (para rodar indefinidamente) e também permitir que seja feito um bind para ele. É simplesmente uma questão de se você 
 implementará dois métodos callback(): onStartCommand() para permitir que os componentes o inicializem e onBind() para permitir que seja feito um bind para ele.

Independente de se a sua aplicação foi iniciada, ligada a uma atividade ou ambas maneiras, qualquer componente de aplicação pode usar o serviço (mesmo de uma aplicação separada) da mesma maneira que qualquer componente pode usar uma atividade - quando iniciada por um Intent. Contudo, você pode declarar o serviço como privado no arquivo de manifesto e bloquear o acesso a ele a partir de outras aplicações.

Cuidado: Um serviço roda na thread principal do processo hospedeiro - o serviço não cria seu próprio thread e não roda em um processo separado (a não ser que você especifique em contrário). Isso significa que se seu serviço está usando muita CPU ou bloqueando operações (como playback de MP3 ou serviços de rede), você deve criar uma nova thread dentro do serviço para fazer o trabalho. Usando uma thread separada, você reduzirá o risco de erros do tipo Application Not Responding (ANR) e a thread principal da aplicação pode remanescer dedicada exclusivamente com a interação do usuário em suas atividades.

Devo usar um serviço ou uma thread?

Um serviço é simplesmente um componente que roda em background mesmo quando o usuário não está interagindo com a aplicação. Ou seja, você só deverá criar um serviço se realmente necessitar.

Se você precisar realizar trabalhos fora da thread principal, mas apenas enquanto o usuário está interagindo com sua aplicação, então você deve provavelmente criar uma nova thread e não um serviço. Por exemplo, se você quer tocar música mas apenas enquanto a atividade estiver rodando, você deve criar uma thread em onCreate(), iniciá-la com onStart() e então parar usando onStop(). Considere também usar AsyncTask ou HandlerThread ao invés da classe tradicional Thread. Quando falarmos de processos e threads esse conceito ficará mais claro.

Lembre-se que se você usar um serviço ele vai rodar na thread principal da sua aplicação por default, então você deve criar uma nova thread dentro do serviço se ele realiza operações intensivas e que bloqueiam outras operações.

O básico

Para criar um serviço, você deve criar uma subclasse de Service (ou uma de suas subclasses existentes). Em sua implementação, você precisará fazer o override de algums métodos callback para manusear aspectos chaves de seu ciclo de vida e prover um mecanismo para componentes fazerem o bind a ele, se apropriado. Os mais importantes métodos callback que você deverá fazer o override são:

onStartCommand()
O sistema chama esse método quando outro componente, como uma atividade, faz a requisição para que o serviço seja iniciado chamando startService(). Uma vez que esse método é executado, o serviço é iniciado e pode roda em background indefinidamente. Se você implementar isso é sua responsabilidade parar o serviço uma vez que o trabalho está feito, chamando stopSelf() ou stopService(). Se você quiser prover apenas o binding, não é necessário implementar esse método.
 
onBind()
O sistema chama o método quando outro componente quer fazer o bind com o serviço (para realizar um Remote Procedure Call - RPC) chamando bindService(). Em sua implementação desse método você deve prover uma interface que os clientes usarão para comunicar com o serviço, retornando um IBinder. Você deve sempre implementar esse método mas se você não quer permitir o binding, então deve retornar null.

onCreate()
O sistema chama esse método quando o serviço é criado pela primeira vez, para realizar procedimentos de configuração iniciais (antes mesmo de chamar ou o onStartCommand() ou onBind()). Se o serviço já está rodando, esse método não é chamado.

onDestroy()
O sistema chama esse método quando o serviço não está mais sendo usado e está sendo destruído. Seu serviço deve implementar esse método para limpar os recursos como threads, listeners registrados, receivers, etc. Esse é a última chamada que o serviço recebe.

Se um componente inicia um serviço chamando startService() (que resulta em uma chamada para onStartCommand()), então o serviço permanece rodando até ser parado com stopSelf() ou outro componente chamando stopService().

Se um componente chama o bindService() para criar o serviço (e o onStartCommand() não foi chamado) então o serviço roda apenas enquanto o componente estiver ligado a ele. Uma vez que o serviço foi desligado de todos os seus clientes, o sistema o destrói.

O sistema Android vai forçar a parada de um serviço apenas quando a memória do dispositivo estiver muito baixa e ele precisar recuperar recursos para uma atividade que está em foco para o usuário. Se o serviço está ligado a uma atividade que tem o foco, então é menos provável que ele seja morto e se o serviço está declarado para rodar em tela (item discutido em posts futuros), então é bem provável que ele nunca seja morto. De outra maneira, se o serviço foi iniciado e está rodando um processo longo, então o sistema vai diminuir sua posição na lista de processos em background e pode se tornar sucetível a ser morto pelo sistema.

Declarando um serviço no manifesto

Como uma atividade (e outros componentes), você deve declarar todos os serviços no arquivo de manifesto da aplicação.

Para declarar seu serviço, adicione um elemento <service> como filho de um elemento <application>.

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

Existem outros atributos que você pode incluir no elemento <service> que definem propriedades como permissões requeridas para a inicialização de tal serviço e o processo no qual o serviço pode rodar.

Assim como uma atividade, um serviço pode definir intent filters que permitem outros componentes chamarem o serviço usando intents implicitos. Declarando intent filters, os componentes de qualquer aplicação instalada no dispositivo podem potencialmente iniciar seu serviço se seu serviço declara um intent filter que é igual ao intent que outra aplicação passou para o startService().

Se você planeja usar seu serviço apenas de modo local (outras aplicações não podem usá-lo), então não é necessário (e você não deveria) suprir quaisquer intent filters. Sem um intent filter você deve iniciar o serviço usando um intent que explicitamente nomeie a classe do serviço.

Adicionalmente, você pode assegurar que seu serviço seja privado para sua aplicação apenas incluindo o atributo android:exported e setá-lo como false. Isso é efetivo mesmo que o serviço forneça intent filters.

0 comentários:

Portions of this page are modifications based on work created and shared by the Android Open Source Project and used according to terms described in the Creative Commons 2.5 Attribution License.
Related Posts Plugin for WordPress, Blogger...