terça-feira, 8 de maio de 2012

Como enviar e receber SMS em um Aplicativo Android

SMS, que significa Short Message Service (Serviço de Mensagens Curtas), se popularizou nos dispositivos móveis há bastante tempo e no Brasil ficou popularmente conhecido como Torpedo. Consiste no envio de mensagens com até 160 caracteres para um celular.

Em suas aplicações para Android você pode querer ou precisar fazer uso deste recurso. A plataforma Android fornece bons métodos de envio e recebimento de SMS pela aplicação e isso é importante pois além de poder enviar um SMS sua aplicação pode ler um SMS e executar alguma ação a partir dele, ou seja, você pode usar SMS para que aplicativos em dispositivos distintos troquem informações e executem ações remotamente.

Se você deseja apenas enviar um SMS simples, onde o usuário possa modificar a mensagem antes de enviar, escolher da agenda o contato e você não precisar ter controle de saber se o SMS foi enviado ou não e nem precisa salvar essas informações então o melhor jeito é usar o aplicativo de mensagens do próprio dispositivo do usuário, pois além de abstrair muito o seu trabalho como desenvolvedor também facilita a vida do usuário oferecendo uma interface que ele já conhece.

Então o que precisamos fazer é apenas chamar o aplicativo de mensagens com o texto que queremos passar e/ou o número:

Intent smsIntent = new Intent(Intent.ACTION_VIEW);
smsIntent.setType("vnd.android-dir/mms-sms");
smsIntent.putExtra("address", "NUMERO DO TELEFONE");
smsIntent.putExtra("sms_body","MENSAGEM A SER ENVIADA");
startActivity(smsIntent);

Feito isso a mensagem e número é passado para outra aplicação e não nos preocupados com o envio propriamente dito. Usei essa estratégia no aplicativo Mensagens para Celular.

Mas se você quiser enviar o SMS direto da sua aplicação o processo é um pouco mais complexo mas ainda bastante simples. Primeiro pega-se a instancia do SmsManager:

SmsManager smsManager = SmsManager.getDefault();

Depois utiliza o seguinte comando se você tiver certeza que sua mensagem terá menos de 160 caracteres:

smsManager.sendTextMessage("07187853344", null, "Mensagem que estou enviando", null, null);
Sendo os parâmetros:
  1. Número que irá receber o SMS;
  2. "Centro de serviço" usado, use null;
  3. A mensagem a ser enviada;
  4. Um PendingIntent que será "broadcastada" quando o SMS for enviado;
  5. Um PendingIntent que será "broadcastada" quando o SMS for recebido;
Se você não tem certeza se sua mensagem será menor que 160 caracteres use o seguinte método:

smsManager.sendMultipartTextMessage ("07187853344", null, smsManager.divideMessage("Mensagem muito grande que estou enviando"), null, null);

O parâmetros são os mesmos o que muda agora é que usamos uma função para quebrar a mensagem caso seja necessário, e passamos também uma lista de PendingIntent ao invés de apenas uma (uma PendingIntent para cada pedaço da mensagem). Usei essa estratégia no aplicativo Amor por SMS.

Para usar esses métodos é necessário declarar uma permissão no AndroidManifest:

<uses-permission android:name="android.permission.SEND_SMS"/>

Aproveitando que estamos no AndroidManifest, para receber mensagens é necessario declarar:

<uses-permission android:name="android.permission.RECEIVE_SMS"/>
E declarar também o BroadcastReceiver que irá receber a chegada do SMS. Coloque isso antes de </application>:

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

Feito isso vamos criar nossa classe SmsReceiver:

public class SmsReceiver extends BroadcastReceiver
{
    @Override
    public void onReceive(Context context, Intent intent) 
    {
        Bundle bundle = intent.getExtras();        
        SmsMessage[] msgs = null;
        String str = "";            
        if (bundle != null)
        {
            Object[] pdus = (Object[]) bundle.get("pdus");
            msgs = new SmsMessage[pdus.length];            
            for (int i=0; i<msgs.length; i++){
                msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]);    
            }
         // Fazer algo com msgs
        }                         
    }
}

Agora você terá provavelmente apenas um SmsMessage na lista mas pode haver mais, e pode fazer o que quiser com esse objeto. Através do comando getDisplayOriginatingAddress() é possível pegar o número que enviou o SMS e através do comando getDisplayMessageBody() pegar o conteúdo da mensagem.

E como fazer par testar o recebimento de SMS pelo emulador? Muito simples! Basta ir na perspectiva DDMS, com o emulador rodando, seleciona-lo e logo em baixo, em Telephony Actions, digitar um número, selecionar SMS, digitar uma mensagem e clicar em send. Como mostra na figura:



É só isso. Mas as possibilidades são imensas! Por exemplo, um aplicativo que responde automaticamente com a posição ao receber um SMS, fazer algum tipo de jogo a 2 usando SMS para comunicação, etc.

33 comentários:

Unknown at 22 de agosto de 2012 às 22:50 disse...

Muito bom tutorial deu certinho aqui. aproveitando gostaria de perdir uma ajuda, como fez pra cria a opcao enviar para outras midias no seu app amor por sms, quando precionamos a mensagem q desejamos enviar???
agradeco desde ja
abs
sandro

Gustavo Carvalho at 23 de agosto de 2012 às 13:26 disse...

@Sandro É muito simples. Exemplo:

Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, "Essa é a String a ser compartilhada. Substitua pela String que quiser");
startActivity(Intent.createChooser(intent, getString(R.string.selecionar_midia)));

Thiago at 26 de setembro de 2012 às 12:28 disse...

fiz como tutorial de envio sms direto testei
, nao esta enviando nao para um numero fictício no emulador . o que pode ter dado errado? Obg

Gustavo Carvalho at 1 de outubro de 2012 às 11:21 disse...

@Thiago: Não entendi muito bem, mas acho que não tem como enviar sms pelo emulador.

Natural Estética at 28 de outubro de 2012 às 13:22 disse...
Este comentário foi removido pelo autor.
Anônimo at 28 de outubro de 2012 às 13:24 disse...

Olá Gustavo, ótimo tutorial, sou iniciante em Android e consegui fazer a aplicação enviar e receber sms, mas tenho um seguinte problema, eu preciso passar um dado recebido por mensagem para uma MapActivity, por exemplo, eu recebo um sms com coordenadas de um mapa, então pego essas coordenadas na classe BroadcastReceiver e mando para uma Activity que contem um MapView e que irá exibir estas coordenadas, por um acaso você teria uma dica que possa me ajudar, já tentei de várias formas e não obtive sucesso. Obrigado.

Gustavo Carvalho at 19 de novembro de 2012 às 05:44 disse...

@Renan: Olá! Sei que a resposta está um pouco atrasada mas enfim... Você pode receber sua mensagem por um BroadcastReceiver e chamar sua Activity e passar as informações da mensagem através dos Extras da propria Intent usada para chamar a Activity. Alternativamente, se sua activity já estiver rodando, você poderia usar o LocalBroadcastManager para mandar uma mensagem especifica para essa Activity, mas acredito que a primeira opção seja mais o seu caso.

Anônimo at 29 de novembro de 2012 às 09:22 disse...

Descobri esta semana a aplicação CrowdSMS. É a ideal para enviar SMS quando estamos assistir um concerto ou numa festa em que está muita gente e não conseguimos enviar a sms. (https://play.google.com/store/apps/details?id=pt.vu.carlosfernandes.crowdsms)

Anônimo at 30 de novembro de 2012 às 11:12 disse...

@Felipe Opa excelente post, tenho uma dúvida. Gostaria de saber de como seria um enviar email pela app e seu eu puder abusar um exemplo de como criar um evento pela app, por exemplo quando for dia tal e hora tal lançar um Toast e vibrar de 20 em 20 min 3 vezes por exemplo seria algo parecido com o alarme só que o alarme só verifica hora enfim rsrs. Se possível ok? obrigado.

Gustavo Carvalho at 6 de dezembro de 2012 às 05:11 disse...

@Anônimo: Você pode enviar e-mail por Intents, isso é, seu app vai mandar informações para que outro app (como o gmail) mande o email:

/* Create the Intent */
final Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);

/* Fill it with Data */
emailIntent.setType("plain/text");
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[]{"to@email.com"});
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Subject");
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, "Text");

/* Send it off to the Activity-Chooser */
context.startActivity(Intent.createChooser(emailIntent, "Send mail..."));


Para enviar diretamente do seu app você precisaria ter acesso a um servidor de e-mail, e não sei como seria feito isso exatamente.

Para criar o evento você pode usar AlarmManager, onde, basicamente, você programa um pedaço de código (PendingIntent) para ser executado em um determinado momento no futuro.

Gabriel Dilly at 12 de dezembro de 2012 às 22:04 disse...

Segui os passos mas alguns coisa não deu certo. Você pode disponibilizar os códigos só pra eu conferir?
Vlw

Gustavo Carvalho at 16 de dezembro de 2012 às 07:20 disse...

@Gabriel: O que exatamente você tentou fazer? Não tenho mais o código completo que usei mas todo o código necessário está aqui na postagem. Cheque coisas como o AndroidManifest, as vezes são pequenas coisas que fazem o programa não funcionar.

Gabriel Dilly at 18 de dezembro de 2012 às 23:38 disse...

@Gustavo: Eu vou revisar de novo os códigos. Vlw

Concentra Mas Não Sai at 11 de março de 2013 às 12:45 disse...

Parabéns pelo tutorial.
Se for instalado num aparelho, como fica a "concorrência" com programa de mensagens? Ou seja, ao chegar uma mensagem, ela será recebida pelo aplicativo nativo e nessa aplicação?
Obrigado / Marcelo

Gustavo Carvalho at 19 de março de 2013 às 09:50 disse...

Será recebida pelos dois e por mais qualquer app que esteja "ouvindo" novas mensagens.

Anônimo at 23 de abril de 2013 às 01:15 disse...

cara eu não entendi como faz esse aplicativo sou novato alguém tem como disponibilizar o projeto?

Anônimo at 24 de abril de 2013 às 12:14 disse...

da para impedir que o recebedor normal de sms do tlm nao receba as sms que nos recebemos no nosso programa?

Unknown at 29 de abril de 2013 às 13:01 disse...

Muito obrigado!!

Habbo DCR at 18 de julho de 2013 às 00:46 disse...

olá, queria saber como selecionar o chip que será usado para enviar a mensagem caso o aparelho seja dual sim, ou tenha mais de 2 ou 3 chips... agradeço

Unknown at 20 de julho de 2013 às 14:35 disse...

funcionou, mas envio as mensagens para meus clientes. o problema é que volta e meia aparece a mensagem "...um grande número de mensagens SMS esta sendo enviada..." e trava tudo, como posso tratar isso?

Unknown at 20 de julho de 2013 às 19:03 disse...

Gustavo fiz minha aplicação de sms, mas gostaria de implementar algo mais como: bloquear o recebimento de alguns numeros escolhido pelo usuário! como faço para qnd ele identifica o numero matar o broadCast, pois a minha notificação eu interrompo mas a nativa mostra! Agradecido desde ja! Abraços

Unknown at 24 de julho de 2013 às 15:44 disse...

Excelente post Gustavo! Uma dúvida, consigo salvar um texto na tela de sms do aparelho.
Exemplo: Tenho uma aplicação que ler dados de um banco na web e gostaria de salvar essa mensagem na tela de sms para que alerte o usuario.

Abraços

Anônimo at 25 de julho de 2013 às 23:31 disse...

Pergunta muito boba, mas é por q sou iniciante... onde deve ficar a classe SMSreciver? ela deve ser uma classe propria, tem que está dentro do codigo fonte do aplicativo ou tanto faz o local? tutorial excelente bem Objetivo, parabens.

Anônimo at 26 de novembro de 2013 às 16:47 disse...

tem como postar o projeto aqui?

Anônimo at 15 de janeiro de 2014 às 20:50 disse...

Parabens, foi o tutorial mais bem feito que encontrei sobre o assundo, otima didatica, simples e objetiva.

Anônimo at 15 de julho de 2014 às 10:46 disse...

Muito bom o tut.
Onde que fica esse Telephony Actions??

Lim at 7 de outubro de 2014 às 13:39 disse...

a parte de enviar o sms, consegui fazer funcionar testando diretamente no meu telefone, mas não consegui testar a parte de receber o sms.
poderia dar um exemplo :)

Carol. M at 22 de março de 2015 às 23:49 disse...

Esse código gera um app que envia sms grátis?

Clã Winners at 12 de maio de 2015 às 08:43 disse...

Amigo. Quanto cobra por me fazer um servidor de sms.
Aplicação demasiado simples:
Recebe por JSON o numero de telemóvel e a mensagem e envia a mensagem para o numero pretendido. Eu fazia isso mas estou sem tempo para acabar uma outra aplicação.
O tempo de verificação de novas msgs programável e tem de enviar para a base de dados do servidor as mensagens enviadas.

A aplicação é para instalar numa versão de android 2.2.

Unknown at 14 de julho de 2015 às 08:24 disse...

Clã Winners, posso fazer essa aplicação, me ligue (31)9476-2619 (31)8676-3741

Thatá Leão at 11 de outubro de 2015 às 00:36 disse...

Como mando mens anônimas?

Emerson Carlindro at 25 de fevereiro de 2016 às 18:24 disse...
Este comentário foi removido pelo autor.
Emerson Carlindro at 25 de fevereiro de 2016 às 18:26 disse...

O que preciso modificar neste código para que o meu App, pegue um número que for digitado em um EditText?? Ou seja, não quero que meu app já tenha um número configurado no código, quero que ele pegue um número digitado em EditText. Tem como?

Postar um comentário

 
© 2011 Tutoriandroid | Recode by Ardhiansyam | Based on Android Developers Blog