Cursos / Informática para Internet / Dispositivos Móveis / Aula

arrow_back Aula 13 - Services, Content Providers e Broadcast Receivers

Broadcast Receivers

Os Broadcast Receivers são responsáveis por receber eventos que são enviados pelo sistema ou até mesmo por outras aplicações. Estes eventos têm como propósito informar diversos tipos de ocorrências para outros componentes interessados nestas. Pouca bateria, desligamento da tela e chamada recebida são exemplos de eventos enviados pelo sistema que podem ser recebidos por Broadcast Receivers que estejam interessados. Esses eventos são enviados em forma de Intent, através do método sendBroadcast().

Para criarmos um Broadcast Receiver, podemos chamar o método Context.registerReceiver(), para fazer isso dinamicamente, ou então declarar no Manifest o Broadcast Receiver através da tag <receiver>. Uma vez registrado, o Broadcast Receiver passa a receber mensagens enquanto aquele componente que o registrou estiver ativo. Por causa desse comportamento, é importante que o Broadcast Receiver esteja registrado apenas durante a vida do componente que o utiliza, ou seja, se tivermos uma Activity inicializando o Receiver, é importante registrar-se durante o método onResume() e se desligar durante o método onPause(). Isso garante que o tempo registrado do Broadcast Receiver é igual ao tempo de foco que a atividade tem.

Em relação aos tipos de Broadcast Receivers, existem duas principais classes. A primeira delas é a responsável pelos Broadcasts normais. Esses Receivers executam de maneira assíncrona e rodam em ordem indefinida, normalmente ao mesmo tempo.

Já o segundo tipo é o Ordered Broadcast. Os Receivers para eventos desse tipo recebem o evento em ordem previamente definida, baseada na propriedade <priority>, declarada no Intent Filter do Receiver, no Manifest. Neste caso, cada Receiver recebe o Intent em uma ordem predeterminada. Isso cria a possibilidade de que um Receiver que tenha a ordem mais alta anule o evento, consumindo-o e evitando que os próximos na ordem cheguem a vê-lo. Note que caso dois Receivers tenham a mesma <priority>, a ordem de entrega entre eles será definida de maneira arbitrária pelo próprio Android.

Mesmo no caso de um Broadcast normal ser usado, às vezes o sistema executa os Broadcasts um por um para evitar a sobrecarga do sistema. Isso é especialmente verdade quando mais de um Receiver cria processos. Para evitar que o sistema se sobrecarregue com a criação de diversos processos simultâneos e muita informação sendo processada, o Android cuida para que cada Receiver seja executado de uma vez. Mesmo assim, por não serem Ordered Broadcasts, não é possível para um Receiver consumir a requisição, ou mesmo retornar um valor para algum outro Receiver que venha depois.

Uma outra curiosidade bem importante é que, apesar de tanto Activities quando Broadcast Receivers utilizarem Intents como seus mecanismos de comunicação, os Intents utilizados são completamente diferentes de um para outro. Podemos afirmar com toda certeza que um Intent endereçado a Activities nunca iniciará um Receiver e vice-versa. Ou seja, apesar de utilizarem o mesmo mecanismo, os processos pelos quais eles passam é completamente diferente.

Quando se trata de segurança, quatro aspectos devem ser levados em conta. Eles são importantes porque o Broadcast Receiver é, por padrão, uma interface que funciona entre aplicações. Para evitar que problemas aconteçam por causa deles, é importante observar o seguinte:

  • O espaço para os Intents é global, ou seja, se uma ação de um Intent tiver o mesmo nome de outra ação já existente, o Intent poderá ser entregue para qualquer um, gerando um conflito indesejado para a sua aplicação.
  • Quando você registra um Broadcast programaticamente, através do método registerReceiver(), qualquer aplicação pode mandar Intents que atingem o seu Broadcast Receiver. Tenha isso em mente quando for desenvolver um elemento desse tipo.
  • Os Broadcast Receivers, assim como os Services, tem a possibilidade da inclusão do atributo exported no Manifest da aplicação para indicar que o componente não deve ser exportado, ou seja, não deve ser visível para outras aplicações.
  • Quando utilizar o método sendBroadcast(), tenha em mente que qualquer aplicação pode receber o Broadcast enviado. Para evitar isso, é possível configurar uma permissão não nula tanto na requisição quando no recebedor. Isso pode ser feito nos métodos de envio e recepção de Broadcast ou ainda dentro da tag responsável, no Android Manifest, através do atributo <uses-permission>.

Um último ponto importante quando estamos lidando com o Broadcast Receiver é saber o ciclo de vida do componente e o que podemos ou não fazer dentro desse ciclo de vida. Quando estamos implementando um Broadcast Receiver, o método mais importante é o onReceive(), que é responsável por receber e processar um Intent que aquele Receiver esteja registrado para receber. E é justamente esse método que determina o tempo de vida de um componente desse tipo. Quando um Intent do tipo correto chega ao componente, ele é iniciado e o método onReceive() é chamado. Dentro desse método, todo o processamento que deve ser feito pelo Receiver é executado e então ele é finalizado, encerrando seu ciclo de vida ali mesmo.

Vendo esse curto ciclo de vida, podemos entender que nenhuma atividade demasiadamente demorada pode depender desse componente. Imagine, por exemplo, que lançamos uma thread para executar um processamento e retornar para o Receiver quando concluir. É muito provável que, ao buscar o componente para retornar, a thread já encontre o Receiver encerrado, o que geraria um erro de execução. Por esses motivos, é totalmente desencorajado o uso desse tipo de artifício dentro de um Broadcast Receiver.

Além disso, é proibido pelo Android criar Dialogs de dentro de um Broadcast Receiver. A única forma de interface que o componente tem com o usuário é a criação de notificações na área de notificação do sistema. Assim como em um Service, o Broadcast Receiver não tem a capacidade de criar uma tela para interagir com o usuário por si próprio. Também note que, graças ao seu ciclo de vida curto, um Broadcast Receiver não pode se conectar a um serviço de tipo Bound, podendo apenas iniciar um Service com o comando startService(). Para concluir nossos estudos sobre Broadcast Receivers, vamos olhar a Listagem 3, que mostra a implementação de um Broadcast Receiver simples, o qual inicializa ou para um Service baseado na carga da bateria do aparelho. Caso o aparelho esteja com bateria fraca, o Service deve ser parado. Caso volte a estar com a bateria boa, o Service volta a funcionar.

Listagem 3 – Broadcast Receiver que lida com eventos de bateria

A Listagem 3 mostra bem os aspectos básicos necessários para a criação de um Broadcast Receiver. Primeiramente, estendemos da classe BroadcastReceiver. Em seguida, sobrescrevemos o método onReceive(), e então tratamos o Intent recebido de maneira adequada. Perceba que apenas comandos simples são executados dentro do método. Também é importante lembrar que para isso funcionar corretamente, o Manifest deve declarar os Intents que o Broadcast Receiver será capaz de receber.

Com esse exemplo, concluímos nossos estudos sobre Broadcast Receivers e também nossa aula. Estamos chegando perto do fim e aposto que todos já temos diversos conceitos novos em nossa mente para trabalhar. Nesse ponto, já temos capacidade de produzir aplicações bem úteis, dependendo das ideias de cada um. Para completar nossos estudos, temos apenas mais um tema de programação a ser abordado, que é conexão web. Então, nos vemos na próxima aula, sobre internet e Android. Até lá!

Versão 5.3 - Todos os Direitos reservados