A maior rede de estudos do Brasil

Grátis
162 pág.
Apostila Android

Pré-visualização | Página 13 de 32

processos longos em background desprovidos de
interface. Uma aplicação, por exemplo, pode requisitar a um serviço para fazer um download ou
mesmo executar uma música enquanto o usuário interage com a interface ou mesmo sai da aplica-
ção host. A aplicação e o Serviço podem ainda se comunicar entre si.
Por padrão, um serviço sempre é executado na Thread principal da aplicação host. Porém, isto
pode ser configurado para que o serviço inicie outras threads quando é chamado evitando assim que
a interface trave durante uma execução que consuma muito processamento.
Manifest
Para criar um serviço é preciso declarar o nome da classe no Manifest.
1 <manifest ... >
2 ...
3 <application ... >
4 <service android:name=".ExampleService" />
5 ...
6 </application >
7 </manifest >
Código XML 8.1: android:name é o único atributo obrigatório
O servico pode ser utilizado por qualquer aplicação através de um Intent. Se o serviço a ser
implementado for apenas util para a aplicação que o contém, então é preciso explicitar que o serviço
é privado no Manifest.
1 <manifest ... >
2 ...
3 <application ... >
4 <service
5 android:name=".ExampleService"
6 android:exported="false"
7 />
8 ...
9 </application >
10 </manifest >
Código XML 8.2: Tornando o serviço local
www.k19.com.br 59
SERVICES E BROADCASTRECEIVERS 60
Classe Service
Para criar um serviço é preciso implementar uma extensão da classe Service e sobreescrever al-
guns métodos de callback.
onStartCommand() - Método que inicia um serviço indefinidamente. O serviço apenas termina
quando o método stopSelf() é executado a partir do próprio serviço ou quando o método stop-
Service() é executado a partir de outra aplicação.
onBind() - Método que é chamado pelo sistema para associar o serviço a uma aplicação. Ele deve
prover uma interface de comunicação entre ambos. Este método deve ser implementado obri-
gatoriamente, logo, se o serviço não for desenhado para suportar Bind então o método onBind
deve devolver null.
onCreate() - Método chamado pelo sistema no momento da criação do serviço e pode ser utilizado
para realizar pré configurações.
onDestroy() - Método chamado pelo sistema quando o serviço for destruido e pode ser utilizado
para liberar recursos utilizados.
Abaixo temos uma implementação simples de um serviço.
1 public class ExampleService extends Service {
2
3 @Override
4 public void onCreate () {
5 // metodo executado no momento em que o servico e criado
6 }
7
8 @Override
9 public int onStartCommand(Intent intent , int flags , int startId) {
10 // execucao do servico
11 return START_STICKY;
12 }
13
14 @Override
15 public IBinder onBind(Intent intent) {
16 // sem suporte a Binding
17 return null;
18 }
19
20 @Override
21 public void onDestroy () {
22 // metodo executado no momento em que o servico e destruido
23 }
24 }
Código Java 8.1: Extendendo a classe Service
Observe que o método onStartCommand() devolve um inteiro. Este valor indica como o sistema
deve continuar o servico caso o sitema o mate. Existem 3 valores possíveis:
START_NOT_STICKY - Não reinicia o serviço a menos que hajam Intents a serem entregues;
START_STICKY - Reinicia o serviço mas não continua a partir do Intent que estava em execução
mas apenas para os que estavam pendentes;
60 www.k19.com.br
61 SERVICES E BROADCASTRECEIVERS
START_REDELIVER_INTENT - Reinicia o serviço retomando a partir do Intent que estava em exe-
cução.
Lembre-se de que a thread que executa o serviço é a thread principal da aplicação host. Caso o
serviço ocupe muito processamento é preciso que o serviço utilize uma nova thread evitando assim
travamentos na interface. No exemplo abaixo, a classe do servico foi modificada para executar sua
tarefa em uma thread separada.
1 public class ExampleService extends Service {
2
3 private Looper mServiceLooper;
4 private ServiceHandler mServiceHandler;
5
6 // Handler que executa de fato a tarefa do servico em uma thread separada
7 private final class ServiceHandler extends Handler {
8 public ServiceHandler(Looper looper) {
9 super(looper);
10 }
11
12 @Override
13 public void handleMessage(Message msg) {
14 // Implementacao da tarefa do servico
15 ...
16
17 // Parando explicitamente o servico
18 stopSelf(msg.arg1);
19 }
20 }
21
22 @Override
23 public void onCreate () {
24 // Criando a thread responsavel pela execucao da tarefa
25 HandlerThread thread = new HandlerThread("ServiceStartArguments",
26 Process.THREAD_PRIORITY_BACKGROUND);
27 thread.start();
28
29 // Obtendo o Looper da thread e passando como parametro para o Handler
30 mServiceLooper = thread.getLooper ();
31 mServiceHandler = new ServiceHandler(mServiceLooper);
32 }
33
34 @Override
35 public int onStartCommand(Intent intent , int flags , int startId) {
36 Toast.makeText(this , "service starting", Toast.LENGTH_SHORT).show();
37
38 // Para cada chamada ao servico enfileiramos uma tarefa no Handler
39 Message msg = mServiceHandler.obtainMessage ();
40 msg.arg1 = startId;
41 mServiceHandler.sendMessage(msg);
42
43 // Se o servico morrer a partir deste ponto , reiniciar
44 return START_STICKY;
45 }
46
47 @Override
48 public IBinder onBind(Intent intent) {
49 // sem suporte a Binding
50 return null;
51 }
52
53 @Override
54 public void onDestroy () {
55 Toast.makeText(this , "service done", Toast.LENGTH_SHORT).show();
56 }
57 }
Código Java 8.2: Executando o serviço em uma thread a parte
www.k19.com.br 61
SERVICES E BROADCASTRECEIVERS 62
Um detalhe importante é que o método onStartCommand() pode ser chamado pelo sistema di-
versas vezes, uma para cada requisição da aplicação. Cada uma delas vem acompanhada de um id
(startId). Se ao final de uma execução o método stopSelf() for chamado enquanto uma outra requisi-
ção está sendo executada, o serviço terminaria sem completar a segunda execução. Para evitar isto,
o método stopSelf() pode receber um inteiro que representa o id da requisição que terminou. Se o id
for igual ao da última requisição o serviço termina, caso contrário ele continua a executar até que as
requisições acabem.
É muito comum implementar serviços que utilizem sua própria thread para executar as tarefas
requisitadas, desta forma, o framework fornece uma extensão da classe Service que simplifica a cri-
ação de serviços como o mostrado no último exemplo. O código abaixo implementa um serviço que
se comporta como o exemplo anterior utilizando a classe IntentService.
1 public class ExampleService extends IntentService {
2
3 /**
4 * O contrutor e obrigatorio e deve chamar o contrutor da super classe
5 * passando o nome da Thread worker
6 */
7 public ExampleService () {
8 super("ExampleService");
9 }
10
11 /**
12 * Este metodo e chamado pela IntentService a partir de um worker Thread e recebe o
13 * Intent que iniciou o servico. Quando o metodo termina o IntentService para o
14 * servico.
15 */
16 @Override
17 protected void onHandleIntent(Intent intent) {
18 // Implementacao da tarefa do servico
19 }
20 }
Código Java 8.3: Utilizando a classe IntentService
Quando utilizamos a classe IntentService, não é necessário se preocupar em parar o serviço.
Iniciando um serviço
Para dar início a um serviço basta criar um intent e passá-lo como parâmetro ao método start-
Service() como no exemplo a seguir:
1 Intent intent = new Intent(this , ExampleService.class);
2 startService(intent);
Código Java 8.4: Iniciando um serviço
Exercícios de Fixação
1 Crie um novo projeto Android. Use como nome para o projeto Services. O nome do pacote deve
ser br.com.k19.android.cap08, e o nome da activity deve ser MainActivity.
2 Na pasta res/layouts crie um arquivo chamado main.xml. Ele deve conter o seguinte conteúdo:
62 www.k19.com.br
63 SERVICES E BROADCASTRECEIVERS
1 <?xml version="1.0" encoding="utf -8"?>
2 <LinearLayout xmlns:android="http:// schemas.android.com/apk/res/android"