1 / 20

Desenvolvimento para Android Aula 7 - Services

Desenvolvimento para Android Aula 7 - Services. Prof. Markus Endler. 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

trula
Download Presentation

Desenvolvimento para Android Aula 7 - Services

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Desenvolvimento para AndroidAula 7 - Services Prof. Markus Endler

  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. publicclassCallbackLifeCycleExampleService extendsService{int mStartMode;// indica como se comportar caso o service seja destruídoIBinder mBinder;// interface para clientes que fazem a conexão com o service boolean mAllowRebind;// indica se onRebind deve ser utilizado@OverridepublicvoidonCreate(){// O service está sendo criado}@OverridepublicintonStartCommand(Intent intent,int flags,int startId){// O service é iniciando devido a uma chamada a startService()returnmStartMode;}@OverridepublicIBinderonBind(Intent intent){// Um cliente se conectou ao service usando bindService()returnmBinder;}@OverridepublicbooleanonUnbind(Intent intent){// Todos os clientes se desconectaram do service usando unbindService()returnmAllowRebind;}@OverridepublicvoidonRebind(Intent intent){// Um cliente está se re-conectando ao service com bindService(),// depois de onUnbind() ter sido chamado}@OverridepublicvoidonDestroy(){// 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. Extensão da android.app.Service publicclass HelloService extends Service { privatestaticfinal String TAG = HelloService.class.getName(); @Override publicint onStartCommand(Intent intent, int flags, int startId) { Log.d(TAG, "Service iniciou"); returnsuper.onStartCommand(intent, flags, startId); } @Override publicvoid onCreate() { Log.d(TAG, "Service parou"); super.onCreate(); } @Override publicvoid onDestroy() { Log.d(TAG, "Service destruído"); super.onDestroy(); } @Override public IBinder onBind(Intent arg0) { // Retorna nulo quer dizer que clientes não podem se conectar ao service returnnull; } } Exemplo de service Método onStartCommand() é chamado quando algum componente executa o método startService() 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 -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 processde application), ou em um processo independente, sendo acessível e compartilhado para outras aplicações (quando começa com ‘:’) -O atributo android:exporteddetermina se este serviceé visível para outras aplicações através de intentfilters - Atributo android:permissiondefine a permissão necesearia para ativar o 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 <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. Habilidade p/ criar threads publicclass MyService extends Service implements Runnable{ privatestaticfinal String TAG = HelloService.class.getName(); private boolean ativo; @Override publicint onStartCommand(Intent intent, int flags, int startId) { Log.d(TAG, "Service iniciou"); returnsuper.onStartCommand(intent, flags, startId); } @Override publicvoid onCreate() { Log.d(TAG, "Service foi criado"); super.onCreate(); ativo = true; new Thead(this).start(); } @Override publicvoid 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(); } } Exemplo de service com thread Criando uma nova 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 publicclass MainActivity extends Activity { private Handler handler = new Handler() { @Override publicvoid handleMessage(Message message) { ... //tratamento ao objeto Message enviado }; }; publicvoid 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. Para receber e processar a Messsage IntentService deve implementar o método onHandleIntent() Handler e Messenger publicclassDownloadServiceextendsIntentService { ... @OverrideprotectedvoidonHandleIntent(Intentintent) { ... //Execução do service ... Bundle extras = intent.getExtras(); if (extras != null) { Messenger messenger = (Messenger) extras.get("MESSENGER"); Messagemsg = Message.obtain(); msg.arg1 = 0; msg.arg2 = 1; msg.obj = newObject(); 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 android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <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 publicclass MyReceiver extends BroadcastReceiver { @Override publicvoid onReceive(Context context, Intent intent) { Intent service = new Intent(context, HelloService.class); context.startService(service); } }

  19. Exemplo de Activity que Interage com Serviceusando 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 classeMyservice final Messenger mMessenger = new Messenger(new IncomingHandler()); class IncomingHandler extends Handler { @Override 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); break; default: super.handleMessage(msg); } } } • O service estende a classe Handler, queimplementaomédodohandleMessage, • Message érecebida no Intent do onBind()

More Related