SMS no Android!

O SMS (Short Message Service) é o serviço de mensagem mais utilizado no mundo. Pesquisas indicam que existe cerca de 3.6 bilhões de usuários fazem uso desta tecnologia.
Isso acontece por que se trata de uma tecnologia que funciona em qualquer dispositivo independente do sistema operacional. É uma ação básica de um telefone celular, assim como realizar chamadas. Por tanto, as pessoas que tem um Nokia 3310 e as pessoas que tem o Samsung galaxy S4 conseguiram enviar mensagens SMS do mesmo jeito, daí a sua popularidade.

Neste artigo vamos aprender como enviar mensagens SMS no Android.

Existem duas formas de realizar esta ação, a primeira, mais tranquila é a via Intent (para saber mais sobre intent clique aqui).
Onde conseguimos chamar o próprio aplicativo de enviar SMS do Android, passando os nossos parâmetros: Telefone e Mensagem de texto.

Logo abaixo, segue o trecho de código que executa uma Intent chamando o aplicativo nativo de envio de SMS:

Intent smsIntent = new Intent(Intent.ACTION_VIEW);
		smsIntent.setType("vnd.android-dir/mms-sms");
		smsIntent.putExtra("address", telefone);
		smsIntent.putExtra("sms_body",mensagem);
		startActivity(smsIntent);

A outra forma é via a própria API do Android, que disponibiliza alguns componentes para atingir esta funcionalidade.
Primeiro devemos criar um objeto da classe SmsManager (esta classe é provida pela própria API do Android). Com este objeto em mãos devemos chamar o método sendTextMessage, que efetivamente envia a mensagem para o destinatário. Este método pede alguns parâmetros, são eles:
Trecho recolhido da documentação oficial:

destination: the address to send the message to

scAddress: is the service center address or null to use the current default SMSC

text: the body of the message to send

sentIntent: if not NULL this PendingIntent is broadcast when the message is successfully sent, or failed.
The result code will be Activity.RESULT_OK for success, or one of these errors:
RESULT_ERROR_GENERIC_FAILURE RESULT_ERROR_RADIO_OFF RESULT_ERROR_NULL_PDU.
The per-application based SMS control checks sentIntent.
If sentIntent is NULL the caller will be checked against all unknown applications, which cause smaller number of SMS to be sent in checking period.
deliveryIntent if not NULL this PendingIntent is broadcast when the message is delivered to the recipient.
The raw pdu of the status report is in the extended data (“pdu”).

Basicamente precisamos preencher o telefone do destinatário, a mensagem de corpo que será enviada. E registrar dois BroadcastReceiver para tratar eventos que acontecem quando a mensagem é enviada, e quando a mensagem chega no destinatário.

Logo abaixo segue o trecho de código responsável por realizar esta operação:


private void sendSMSByAPI(String phoneNumber, String message) 	{        

		PendingIntent sentPI = PendingIntent.getBroadcast(this, 0,new Intent(SENT), 0);
		PendingIntent deliveredPI = PendingIntent.getBroadcast(this, 0,new Intent(DELIVERED), 0);
		
		SmsManager sms = SmsManager.getDefault();
		sms.sendTextMessage(phoneNumber, null, message, sentPI, deliveredPI);


		registerReceiver(new BroadcastReceiver(){
			@Override
			public void onReceive(Context arg0, Intent arg1) {
				switch (getResultCode())
				{
				case Activity.RESULT_OK:
					showToast("SMS sent");
					break;
				case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
					showToast("Generic failure");
					break;
				case SmsManager.RESULT_ERROR_NO_SERVICE:
					showToast("No service");
					break;
				case SmsManager.RESULT_ERROR_NULL_PDU:
					showToast("Null PDU");
					break;
				case SmsManager.RESULT_ERROR_RADIO_OFF:
					showToast("Radio off");
					break;
				}
			}
		}, new IntentFilter(SENT));

		
		registerReceiver(new BroadcastReceiver(){
			@Override
			public void onReceive(Context arg0, Intent arg1) {
				switch (getResultCode())
				{
				case Activity.RESULT_OK:
					showToast("SMS delivered");
					break;
				case Activity.RESULT_CANCELED:
					showToast("SMS not delivered");
					
					break;                        
				}
			}
		}, new IntentFilter(DELIVERED));        

	        
	}

Observação importante:

Duas permissões devem ser registradas no AndroidManifest.xml. São elas:

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

Agora vamos ao exemplo completo.

No nosso exemplo teremos apenas uma Activity e um layout.xml. O Layout definirá duas entradas do usuário, o telefone do destinatário e a mensagem que ele deseja enviar.

Também estará presente no layout dois botões, o primeiro irá enviar SMS pela Intent e o segundo será responsável por enviar o SMS pela API.

Logo abaixo segue o código do layout xml.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/layout_principal"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:layout_gravity="center"
     >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Digite o telefone:"
         />

    <EditText
        android:id="@+id/edit_text_phone"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:inputType="phone" 
        />
    
        <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Digite a mensagem:"
         />

    <EditText
        android:id="@+id/edit_text_mensagem"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:inputType="text" 
        />
    

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="onClickSMSIntent"
        android:text="SMS Intent" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="onClickSendSMS"
        android:text="SMS API" />

</LinearLayout>

 

Com o layout já definido devemos agora tratar os eventos dos componentes que definimos através de uma Activity. Esta Activity, será vinculada ao layout apresentado acima através do método setContentView(int resLayout) . E chamará os métodos de envio de SMS por Intent e por API que apresentamos anteriormente neste artigo.

Vejamos o código desta Activity logo abaixo:


public class MainActivity extends Activity {
	
	private static final String SENT = "SMS_SENT"; // Enviada
	private static final String DELIVERED = "SMS_DELIVERED"; // Entregue
	
	private EditText editTextMensagem;
	private EditText editTextTelefone;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		editTextMensagem = (EditText) findViewById(R.id.edit_text_mensagem);
		editTextTelefone = (EditText) findViewById(R.id.edit_text_phone);
	}

	public void onClickSMSIntent(View view) {
		sendSMSByIntent();  	
	}

	public void sendSMSByIntent() {
		
		String telefone = editTextTelefone.getText().toString();
		String mensagem = editTextMensagem.getText().toString();
		
		Intent smsIntent = new Intent(Intent.ACTION_VIEW);
		smsIntent.setType("vnd.android-dir/mms-sms");
		smsIntent.putExtra("address", telefone);
		smsIntent.putExtra("sms_body",mensagem);
		startActivity(smsIntent);
	}

	public void onClickSendSMS(View view) {
		String telefone = editTextTelefone.getText().toString();
		String mensagem = editTextMensagem.getText().toString();
		
		sendSMSByAPI(telefone, mensagem);
	}

	private void sendSMSByAPI(String phoneNumber, String message) 	{        

		PendingIntent sentPI = PendingIntent.getBroadcast(this, 0,new Intent(SENT), 0);
		PendingIntent deliveredPI = PendingIntent.getBroadcast(this, 0,new Intent(DELIVERED), 0);
		
		SmsManager sms = SmsManager.getDefault();
		sms.sendTextMessage(phoneNumber, null, message, sentPI, deliveredPI);

		registerReceiver(new BroadcastReceiver(){
			@Override
			public void onReceive(Context arg0, Intent arg1) {
				switch (getResultCode())
				{
				case Activity.RESULT_OK:
					showToast("SMS sent");
					break;
				case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
					showToast("Generic failure");
					break;
				case SmsManager.RESULT_ERROR_NO_SERVICE:
					showToast("No service");
					break;
				case SmsManager.RESULT_ERROR_NULL_PDU:
					showToast("Null PDU");
					break;
				case SmsManager.RESULT_ERROR_RADIO_OFF:
					showToast("Radio off");
					break;
				}
			}
		}, new IntentFilter(SENT));
		
		registerReceiver(new BroadcastReceiver(){
			@Override
			public void onReceive(Context arg0, Intent arg1) {
				switch (getResultCode())
				{
				case Activity.RESULT_OK:
					showToast("SMS delivered");
					break;
				case Activity.RESULT_CANCELED:
					showToast("SMS not delivered");
					
					break;                        
				}
			}
		}, new IntentFilter(DELIVERED));        
	        
	}
	
	private void showToast(String message) {
		Toast.makeText(getBaseContext(), message,Toast.LENGTH_SHORT).show();
	}
}
Anúncios

, , , , ,

  1. #1 by Thiago on Abril 8, 2014 - 4:03 pm

    Estou tendo um conflito nos métodos sendTextMessage e getDefault, para para importar uma anotações? está correto. Preciso importar realmente essas anotações?

  2. #2 by Guilherme on Setembro 3, 2013 - 12:11 am

    Leonardo, tem um furo no BroadcastReceiver, cada vez que o sendSMSByAPI é chamado ele registra um BroadcastReceiver, quando vc sai da app ela da um erro de Broadcast não “desrregistrado”. Mesmo mantendo a referencia não iria funcionar, pq cada chamada cria um objeto diferente e você teria sempre a referência ao último objeto criado. Uma segunda opção seria criar uma lista de BroadcastReceiver, mas dependendo da app iria entupir a activity de objetos.
    Eu resolvi com algo não muito satisfatório, no final do onReceive a ultima coisa é unregisterReceiver(this);
    Tem alguma ideia melhor?

    • #3 by Leonardo Casasanta on Setembro 3, 2013 - 12:46 am

      Ola Guilherme, achei a sua solução legal. Porém, eu gosto da ideia de ter um BroadcastReceiver fora da Activity. Acho que fica desacoplado, outras Activitys e até outros sistemas podem fazer uso deste BroadcastReceiver. Além do mais o ciclo de vida do BroadcaastReceiver não vai ficar mais ligado ao ciclo de vida da Activity. Espero ter ajudado. Obrigado pelo comentário!

  3. #4 by Guilherme on Setembro 2, 2013 - 12:54 am

    Exemplo completo, todos os exemplos que achei por ai não demonstravam o broadcast, passavam null…. valeu!

Deixe uma Resposta

Preencha os seus detalhes abaixo ou clique num ícone para iniciar sessão:

Logótipo da WordPress.com

Está a comentar usando a sua conta WordPress.com Terminar Sessão / Alterar )

Imagem do Twitter

Está a comentar usando a sua conta Twitter Terminar Sessão / Alterar )

Facebook photo

Está a comentar usando a sua conta Facebook Terminar Sessão / Alterar )

Google+ photo

Está a comentar usando a sua conta Google+ Terminar Sessão / Alterar )

Connecting to %s

%d bloggers like this: