Desenvolvimento para Android Aula 7 - Services - ppt carregar
PublicouMikaela Rocha Alterado mais de 3 anos atrás
Apresentação em tema: "Desenvolvimento para Android Aula 7 - Services"— Transcrição da apresentação:
1 Desenvolvimento para Android Aula 7 - Services
2 Services Um service é um tipo de componente de uma aplicação Android que é utilizado para executar operações de longa duração em background Services não possuem interface gráfica para o usuário São utilizados para operações de rede, processamento intenso, tocar músicas, etc. Por exemplo, em uma aplicação que toca músicas, uma música deve continuar a ser tocada para o usuário independente do que o mesmo esteja fazendo no dispositivo A comunicação pela rede pode demorar, e por isso é importante que ocorra de forma assíncrona (sem bloquear a app) Podem executar de forma independente do componente que os criou Se uma activity inicia um service e esta é fechada, o service continuará executando em background Podem ser conectados a quaisquer outros componentes de aplicação (de acordo com as permissões) Por exemplo, é possível permitir que qualquer aplicação possa conectar-se ao service e manipulá-lo
3 Services – Formas Um service pode assumir duas formas:
Não-conectado (unbounded) Um service é criado quando outro componente chama(*) o método startService(), pasando um Intent O service executa indefinidamente (mesmo que o componente criador termine) e pode se parar chamando o método stopSelf(). Um outro componente pode parar o service diretamente através do chamado stopService(). Quando o service é parado, o sistema destrói o mesmo. Conectado (bounded) Um service é criado quando outro componente chama o método bindService(). O componente (cliente) comunica-se com o service pela interface IBinder – podendo fazer comunicação entre diferentes processos. O cliente pode fechar a conexão com o mesmo através da chamada unbindService(). Múltiplos clientes podem se conectar ao mesmo service e quando todos estes fecham a conexão, o sistema Android destrói o service. (*) Em Android, "chamar" significa criar um Intent corresponente.
4 Services – Formas e Ciclo-de-vida
5 Services – Ciclo-de-vida
public class CallbackLifeCycleExampleService extends Service { int mStartMode; // indica como se comportar caso o service seja destruído IBinder mBinder; // interface para clientes que fazem a conexão com o service boolean mAllowRebind; // indica se onRebind deve ser utilizado public void onCreate() { // O service está sendo criado } public int onStartCommand(Intent intent, int flags, int startId) { // O service é iniciando devido a uma chamada a startService() return mStartMode; } public IBinder onBind(Intent intent) { // Um cliente se conectou ao service usando bindService() return mBinder; } public boolean onUnbind(Intent intent) { // Todos os clientes se desconectaram do service usando unbindService() return mAllowRebind; } public void onRebind(Intent intent) { // Um cliente está se re-conectando ao service com bindService(), // depois de onUnbind() ter sido chamado } public void onDestroy() { // O service não está sendo mais usado e está sendo destruído } } Services – Ciclo-de-vida
6 Services – Informações
Um mesmo service pode funcionar de ambas as formas, bastando que implemente: O método onStartCommand() para permitir que componentes o iniciem O método onBind() para permitir que componentes se conectem ao mesmo Qualquer componente pode utilizar o service, mesmo aqueles que estejam em aplicações separadas Da mesma forma como acontece com uma activity, utiliza-se um intent para ativar um service Se a declaracão do Service no Manifest contiver um Intent filter, isso significa que qualquer componente (de outra app) pode ativa-lo com um implicit intent. Senão, somente pode ser invocado pelo seu nome da classe, através de um intent explicito. Isso é o default do atributo android:exported =["true" |"false"] IMPORTANTE: um service executa normalmente na thread principal do processo que o abriga. Se é necessário executa-lo em um processo separado, deve-se explicitar isto em isolatedProcess e dar o nome em process na declaracão no manifesto Dependendo da utilização do service, deve-se criar uma thread separada para executar suas operações intensivas em recursos e/ou bloqueantes
7 Criação de um service Para desenvolver um service deve-se estender a classe android.app.Service É preciso implementar métodos para atender o ciclo-de-vida e fornecer mecanismos para que seja possível se conectar ao service Obs: em situacões de escassez de memória, o Android também pode destruir um service. Para que estado do service possa ser recriado posteriormente, os métodos do ciclo de vida precisam ser implementados. Os mais importantes métodos são: onStartCommand(): método chamado quando um outro componente solicita que o service seja iniciado utilizado startService() onBind(): método chamado quando um outro componente solicita se conectar ao service através do método bindService() É necessário fornecer uma interface, Ibinder, para os clientes se comunicarem com o service onCreate(): método para procedimentos de configuração inicial do service, chamado quando o service é criado (antes de chamar onStartCommand() ou onBind() onDestroy(): método chamado quando o service não está mais em uso e deve ser destruído – aqui devemos liberar recursos alocados (p. ex. threads)
8 Exemplo de service Extensão da android.app.Service
public class HelloService extends Service { private static final String TAG = HelloService.class.getName(); @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(TAG, "Service iniciou"); return super.onStartCommand(intent, flags, startId); } public void onCreate() { Log.d(TAG, "Service parou"); super.onCreate(); public void onDestroy() { Log.d(TAG, "Service destruído"); super.onDestroy(); public IBinder onBind(Intent arg0) { // Retorna nulo quer dizer que clientes não podem se conectar ao service return null; Extensão da android.app.Service Método onStartCommand() é chamado quando algum componente executa o método startService() Exemplo de service Método onBind() deve retornar interface para chamadas remotas ao service – neste exemplo, não é possível se conectar a este service
9 Declaração de um service
Como os outros componentes Android – activities, content providers e broadcast receivers – um service deve ser declarado no arquivo de manifesto da aplicação para que este seja usado pela aplicação -O único atributo obrigatório é o nome da classe que estende android.app.Service -O atributo android:process determina o processo que executará este service, podendo ser o mesmo da aplicação, privado à aplicação (definido no atributo process de application), ou em um processo independente, sendo acessível e compartilhado para outras aplicações (quando começa com ':') -O atributo android:exported determina se este service é visível para outras aplicações através de intent filters - Atributo android:permission define a permissão necesearia para ativar o service <application> ... <service android:name="HelloService" android:process=":the_process" android:exported="true" android:permission="abc"> </service> </application>
10 IntentService IntentService é uma subclasse de android.app.Service que facilita o desenvolvimento de services e que utiliza uma única thread para tratar todas as requisições para iniciar o service, uma por vez Esta é a melhor opção se o service não precisa tratar requisições concorrentes/simultâneas Basta implementar onHandleIntent() que recebe o intent de cada solicitação de ativação do service A maioria dos services desenvolvidos não tem o requisito de tratar requisições concorrentes Nestes casos, é muito mais fácil utilizar o IntentService como subclasse para implementação do service
11 Iniciando um service Deve-se sempre iniciar um service utilizando intents com o método startService() O Android chamará o método startCommand() passando como parâmetro o intent utilizado Múltiplas requisições para iniciar o service vão chamar múltiplas vezes o método onStartCommand() Quando um service não permite a conexão, a única forma de passar dados para o service é através do intent utilizado Intent intent = new Intent(this, HelloService.class); startService(intent);
12 Parando um service Para parar um service, o próprio deve chamar o método stopSelf() ou algum componente deve chamar o método stopService() Quando estes métodos – stopSelf() e stopService() – são chamados, o Android imediatamente destrói o service Contudo, se o service deve receber múltiplas requisições concorrentes para executar tarefas independentes , deve-se utilizar o identificador de cada requisição para controlar quando o service será destruído Atenção: É importante sempre parar o service quando seu trabalho foi finalizado para liberar recursos e não consumir bateria Intent intent = new Intent(this, HelloService.class); stopService(intent);
13 Exemplo de service com thread
Habilidade p/ criar threads public class MyService extends Service implements Runnable{ private static final String TAG = HelloService.class.getName(); private boolean ativo; @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(TAG, "Service iniciou"); return super.onStartCommand(intent, flags, startId); } public void onCreate() { Log.d(TAG, "Service foi criado"); super.onCreate(); ativo = true; new Thead(this).start(); public void onDestroy() { Log.d(TAG, "Service destruído"); super.onDestroy(); ativo = false; public void run() { while (ativo && count < MAX) { fazAlgumaCoisa(); Log.d(TAG, "processando..."); count++; Log.d(TAG, "terminei"); stopSelf(); Criando uma nova thread Exemplo de service com thread Veja: java.lang.Runnable#run() A therad executa um loop chamando fazAlgumaCoisa();
14 Executando em foreground
Um service pode executar em foreground quando é considerado importante para o usuário, e não deva ser termiando quando a memória estiver baixa Para isto, é necessário chamar no próprio service o método startForeground(), que provê para o usuário uma notificação na barra de status Esta notificação sumirá somente quando o service for parado ou tirado do foreground Para tirar o service do foreground deve-se executar o método stopForeground() Notification notification = new Notification(R.drawable.icon, "Notif.", System.currentTimeMillis()); Intent notificationIntent = new Intent(this, ExampleActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); notification.setLatestEventInfo(this, "MonitorService", "Notif.", pendingIntent); startForeground(0, notification);
15 Handler e Messenger O service pode se comunicar de volta com a activity através de um objeto Messenger Este objeto é enviado para o service através do intent Caso este Messenger esteja conectado com um Handler na activity, o service pode enviar objetos Message para a mesma public class MainActivity extends Activity { private Handler handler = new Handler() { @Override public void handleMessage(Message message) { ... //tratamento ao objeto Message enviado }; public void onClick(View view) { Intent intent = new Intent(this, DownloadService.class); Messenger messenger = new Messenger(handler); intent.putExtra("MESSENGER", messenger); startService(intent); } Um novo objeto Messenger é passado como extra do intent
16 Handler e Messenger Para receber e processar a Messsage IntentService deve implementar o método onHandleIntent() public class DownloadService extends IntentService { ... @Override protected void onHandleIntent(Intent intent) { //Execução do service Bundle extras = intent.getExtras(); if (extras != null) { Messenger messenger = (Messenger) extras.get("MESSENGER"); Message msg = Message.obtain(); msg.arg1 = 0; msg.arg2 = 1; msg.obj = new Object(); msg.setData(extras); try { messenger.send(msg); } catch (android.os.RemoteException e1) { ... Método estático Message.obtain() retorna um novo objeto Message O objeto Message contém atributos e métodos para definir dados resultantes do service
17 Executando um service após boot
Existem várias maneiras de agendar um service para execução Pode ser interessante agendar a execução de um service após a inicialização do Android (o boot) Para isto, basta criar um Broadcast Receiver que receba a notificação de que a inicialização completou, e que irá então iniciar o service <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <application > <service android:name="HelloService" android:exported="true" android:process=":the_process"> </service> <receiver android:name="MyScheduleReceiver" > <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver> </application>
18 Executando um service após boot
O BroadcastReceiver é notificado de que o Android finalizou seu boot e solicita o início da execução do service public class MyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Intent service = new Intent(context, HelloService.class); context.startService(service); }
19 Exemplo de Activity que Interage com Service usando Message
Quando o serviço é executado, ele incrementa o número na frequência 10Hz. Quando a Activity faz um bind com o Service, irá exibir o valor atual. É possive também enviar mensagens para o Service para alterar o inclremento. Os dados (integer e string) são transferidos usando Message e Handlers. Estudar o código em https://bitbucket.org/alexfu/androidserviceexample/src
20 Handler na Activity Obs: o Service é a classe Myservice
final Messenger mMessenger = new Messenger(new IncomingHandler()); class IncomingHandler extends Handler public void handleMessage(Message msg) { switch (msg.what) { case MyService.MSG_SET_INT_VALUE: textIntValue.setText("Int Message: " + msg.arg1); break; case MyService.MSG_SET_STRING_VALUE: String str1 = msg.getData().getString("str1"); textStrValue.setText("Str Message: " + str1); default: super.handleMessage(msg); } Obs: o Service é a classe Myservice O service estende a classe Handler, que implementa o médodo handleMessage, Message é recebida no Intent do onBind()