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

4 comentários:

Anônimo disse...

Olá! É possível interceptar o envio de um SMS? Ou apenas o recebimento?

Nelson Glauber disse...

Oi Anônimo,

Nâo facilmente como o recebimento, mas você pode usar um ContentObserver no ContentProvider de SMS. Mas eu não testei essa solução.

4br4ç05,
nglauber

Unknown disse...

Olá, como faço para que as mensagens enviadas não apareçam em ítens enviados?
Obrigado!

Nelson Glauber disse...

Oi Samuel,

Pelo que lembro, a partir do KitKat isso não é mais possível. Dá uma olhada nesse vídeo e qualquer coisa me fala.
https://www.youtube.com/watch?v=mdq0R2WQssQ

4br4ç05,
nglauber