Mostrando postagens com marcador BroadcastReceiver. Mostrar todas as postagens
Mostrando postagens com marcador BroadcastReceiver. Mostrar todas as postagens

segunda-feira, 30 de março de 2015

Explorando libs famosas: Otto

Olá povo,

Acho que todos que me conhecem sabem que eu não sou muito fã de usar libs de terceiros. Principalmente porque na grande maioria das vezes, é mais fácil você entender apenas o código que é puramente Android, do que ter que lembrar ou saber como uma lib realiza determinado comportamento.
Mas como muita gente gosta, resolvi fazer uma série de posts com algumas bibliotecas Android mais famosas no mercado. E pra começar, vamos falar do Otto.

Otto (http://square.github.io/otto/)
Permite registrar e disparar eventos de/para qualquer parte da aplicação. Adicione a dependência a seguir.
dependencies {
  compile 'com.squareup:otto:1.3.6'
}
A primeira coisa a fazer é instanciar um objeto da classe Bus. Um bom local para fazer isso é na classe que herda de Application (lugar perfeito iniciar os singletons).
import android.app.Application;
import com.squareup.otto.Bus;

public class ExplorandoLibsApp extends Application {

  private Bus bus;

  @Override
  public void onCreate() {
    super.onCreate();
    bus = new Bus();
  }

  public Bus getBus() {
    return bus;
  }
}
Não esqueça de declarar essa classe no AndroidManifest.xml.
 
<application
  ...
  android:name=".ExplorandoLibsApp">
Qualquer classe pode ser enviada como evento...
public class UmaClasseQualquer {

  private String mTexto;

  UmaClasseQualquer(String texto) {
    mTexto = texto;
  }

  public String getTexto() {
    return mTexto;
  }
}
E todo método que assinar um evento será notificado. Para assinar um evento, use a anotação @Subscribe. E para disparar o evento utilize o método post(evento) do objeto Bus.
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.widget.Toast;
import com.squareup.otto.Bus;
import com.squareup.otto.Subscribe;

public class MainActivity extends ActionBarActivity {

    private Bus mBus;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);

      mBus = ((ExplorandoLibsApp)getApplication())
             .getBus();
      mBus.register(this);
    }

    public void dispararEventoOtto(View v){
      mBus.post(new UmaClasseQualquer("Mensagem"));
    }

    @Subscribe
    public void chegouEvento(UmaClasseQualquer event) {
      Toast.makeText(this, event.getTexto(), 
        Toast.LENGTH_SHORT).show();
    }
}
Obtemos a instância do Bus no onCreate() e informamos que essa classe ouvirá eventos do Bus por meio do método register. O método dispararEventoOtto() é invocado ao clicar em um botão, e nele disparamos o evento chamando o método post(). Quando isso ocorre o método chegouEvento() é invocado.

Outra biblioteca que realiza o mesmo trabalho é o EventBus.

Podemos realizar comportamento similar utilizando as classes BroadcastReceiver e LocalBroadcastManager.

4br4ç05,
nglauber

sábado, 4 de dezembro de 2010

Enviando e Recebendo SMS no Android

Olá povo,

Questionar é uma coisa muito sábia. Quando estava dando aula sobre SMS um aluno (Renato se não me engano) questionou meu código, que na verdade estava muito similar (pra não dizer igual) ao código do livro de Ricardo Lecheta. Quando paramos pra analisar vimos como ficou fácil interceptar um SMS.

Primeiro devemos criar um BroadcastReceiver e registrá-lo no AndroidManifest.xml para ser disparado quando a ação "android.provider.Telephony.SMS_RECEIVED" for disparada pelo sistema operacional. Além disso, deve-se utilizar as permissões para enviar e receber SMS.


public class SmsReceiver extends BroadcastReceiver {

public void onReceive(Context context, Intent it){
SmsMessage message =
SMSUtils.getMessagesFromIntent(it)[0];

Toast.makeText(context,
"Mensagem recebida de "+
message.getOriginatingAddress() + " - "+
message.getMessageBody(),
Toast.LENGTH_LONG).show();
}
}


<receiver android:name="SmsReceiver">
<intent-filter>
<action
android:name="android.provider.Telephony.SMS_RECEIVED"/>
<category
android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>

<!-- Adicione essas permissões na tag manifest -->
<uses-permission
android:name="android.permission.RECEIVE_SMS"/>
<uses-permission
android:name="android.permission.SEND_SMS"/>



public class SMSUtils {

public void enviarSms(String numero, String msg) {

SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage(numero, null, msg,
null, null);
}

public static SmsMessage[] getMessagesFromIntent(
Intent intent){

Object[] pdusExtras =
(Object[])intent.getSerializableExtra("pdus");

SmsMessage[] messages =
new SmsMessage[pdusExtras.length];

for (int i = 0; i < pdusExtras.length; i++) {
messages[i] = SmsMessage.createFromPdu(
(byte[])pdusExtras[i]);
}
return messages;
}

}// end class


O Android utiliza o formato de mensagens em PDU que permite a leitura de SMS em vários encondings. Por isso, ao receber as mensagens, lemos a informação extra da intent chamada de "pdus". Essa informação é um array de arrays de bytes. Percorremos o array de bytes (que em cada posição tem outro array) e passamos cada array para um método que cria a mensagem SMS. Uma vez com o objeto android.telephony.SmsMessage, podemos obter as informações como telefone de origem e texto da mensagem.

Quando a mensagem é recebida ela vai para a caixa de entrada. Para excluírmos a mensagem recebida, basta usar o content provider da aplicação de SMS conforme explicado nesse post

Se quisermos evitar que a mensagem chegue na aplicação de mensagens, basta colocar uma prioridade (android:priority) maior do que a da aplicação de mensagens no intent-filter do Broadcast que recebe o SMS. E dentro dele, chamar o método abortBroadcast().

4br4ç05,
nglauber

sábado, 24 de julho de 2010

Capturando Eventos do Sistema com Android

Olá pessoal,

A facilidade da plataforma Android me encanta muito, nunca programei com nada tão bacana. Por isso, vou falar um pouquinho sobre como capturar eventos do sistema utilizando BroadcastReceivers. A classe android.content.BroadcastReceiver é utilizada para receber eventos de sistema (ou nossos próprios) e tratá-los em background. Ela não possui interface gráfica associada e possui um tempo de vida muito curto (cerca de 10 segundo), então se quisermos mostrar algum feedback pro usuário devemos delegar isso pra uma Activity.

Para implementarmos um BroadcastReceiver basta criar uma classe que a estenda, implementar o método onReceive(Context, Intent) e registrá-la com a tag <receiver> AndroidManifest.xml ou no código através do método context.registerReceiver(receiver, filtro). Para desativar podemos utilizar uma chamada para context.unregisterReceiver(receiver). Se quisermos enviar nossa própria mensagem de broadcast, podemos chamar o método sendBroadcast(Intent).

No nosso exemplo, capturaremos as mudanças de estado do telefone. Ou seja, quando for feita, recebida ou terminada uma ligação, nosso BroadcastReceiver entrará em ação.

Primeiro, crie a classe conforme abaixo:

public class InterceptCall extends BroadcastReceiver {

 public void onReceive(Context ctx, Intent it) {
   String estado = it.getStringExtra("state");
   String num = it.getStringExtra("incoming_number");
   String msg = null;
     
   if (estado.equals("RINGING")){
     msg = "O número "+ num +" está chamando.";
         
   } else if (estado.equals("OFFHOOK")){
     msg = "Em ligação.";
       
   } else if (estado.equals("IDLE")){
     if (num != null){
       msg = "Chamada não atendida de "+ num;
     } else {
       msg = "Chamada atendida, foi terminada.";
     }
   }
     
   Toast.makeText(ctx, msg, Toast.LENGTH_LONG).show();
 }
}
Com esse receiver, capturamos a mudança de estado do telefone em ligações. A Intent que o dispara tem dois extras: state e incoming_number. O primeiro indica o estado do telefone e o segundo o número do telefone de quem está ligando. O telefone vai para o estado RINGING (tocando) quando o telefone está recebendo a ligação. Ao atender ou fazer uma chamada o telefone vai para o estado OFFHOOK (fora do gancho). E por último, ao terminar uma ligação o telefone volta para o seu estado padrão, IDLE (parado).

Notem que nem OFFHOOK e nem IDLE quando não se atende a ligação, contam com o número do telefone que o chamou.

Para finalizar, basta registrarmos o nosso BroadcastReceiver no AndroidManifest.xml, dentro da tag <application>, conforme abaixo:

<receiver android:name="InterceptCall">
<intent-filter>
  <action
  android:name="android.intent.action.PHONE_STATE"/>
  <category
  android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
Também adicione a permissão para ler o estado da ligação no AndroidManifest.xml FORA DA TAG .
<uses-permission 
  android:name="android.permission.READ_PHONE_STATE"/>
Pronto! Agora é só brincar com os demais eventos do sistema.

4br4ç05,
nglauber