En este tutorial te mostraremos un ejemplo práctico paso a paso sobre cómo enviar, recibir y listar el historial de SMS con Android para tus propios proyectos. Intentaremos explicar las distintas vías para hacer esto posible así como un pequeño desarrollo donde veréis todo lo explicado en práctica. Sin más dilación, paso a explicaros como enviar, recibir y ver el historial de SMS con Android
Podemos enviar SMS a través de 2 vías - con intent o sin intent. Cualquier envío de SMS requiere permiso android.permission.SEND_SMS:
<manifest ...>
<uses-sdk .../>
<uses-permission android:name="android.permission.SEND_SMS"/>
<application
...>
...
</manifest>
Enviar SMS
Con Intent
Directamente a través de la aplicación SMS / MMS
Esto código fuerza a la aplicación SMS/MMS de Android a abrirse con un número de teléfono y un texto SMS especificado. A continuación, el usuario puede pulsar el botón "Enviar", y se enviará el SMS.
Requiere el permiso android.permission.SEND_SMS (ver arriba).
strPhone = "XXXXXXXXXXX"; strMessage = "LoremnIpsum"; Intent sendIntent = new Intent(Intent.ACTION_VIEW); sendIntent.setType("vnd.android-dir/mms-sms"); sendIntent.putExtra("address", strPhone); sendIntent.putExtra("sms_body", strMessage); startActivity(sendIntent);
A través de aplicaciones por defecto
Este código ejecuta la url "smsto: + XXXXXXXXXXX", Android lo procesa, y ejecuta la aplicación por defecto que está asignada para manejar el protocolo smsto.
Por defecto, es la aplicación SMS/MMS de Android (ver intent de más arriba). Pero si instalamos cualquier aplicación de terceros que también pueda manejar SMS y se establezca como manejador smsto (es decir, Skype), la primera vez que recibamos uno de estos SMS nos aparecerá una ventana donde debemos elegir entre la aplicación integrada y esta aplicación de terceros. Todo un inconveniente.
Requiere el permiso android.permission.SEND_SMS (ver arriba).
strPhone = "XXXXXXXXXXX"; strMessage = "LoremnIpsum"; Uri sms_uri = Uri.parse("smsto:+" + strPhone); Intent sms_intent = new Intent(Intent.ACTION_SENDTO, sms_uri); sms_intent.putExtra("sms_body", txtMessage.getText().toString()); startActivity(sms_intent);
Sin Intent
SmsManager.sendTextMessage()
Requiere el permiso android.permission.SEND_SMS (ver arriba).
String strPhone = "XXXXXXXXXXX"; String strMessage = "LoremnIpsum"; SmsManager sms = SmsManager.getDefault(); sms.sendTextMessage(strPhone, null, strMessage, null, null); Toast.makeText(this, "Sent.", Toast.LENGTH_SHORT).show();
SmsManager.sendMultipartTextMessage() - Si el mensaje es más largo de 160 caracteres
Si el tamaño del SMS supera cierto límite (normalmente son 160 caracteres), la función sendTextMessage() no lo enviará. Debemos usar sendMultipartTextMessage() en estos casos.
Requiere el permiso android.permission.SEND_SMS (ver arriba).
String strPhone = "XXXXXXXXXXX"; String strMessage = "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890TEST"; SmsManager sms = SmsManager.getDefault(); ArrayList messageParts = sms.divideMessage(strMessage); sms.sendMultipartTextMessage(strPhone, null, messageParts, null, null); Toast.makeText(this, "Sent.", Toast.LENGTH_SHORT).show();
Comprobar si el dispositivo puede enviar SMS
PackageManager pm = this.getPackageManager(); if (!pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY) && !pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CDMA)) { Toast.makeText(this, "Lo sentimos, tu dispositivo probablemente no pueda enviar SMS...", Toast.LENGTH_SHORT).show(); }
Recibir SMS
Permisos:
<manifest ...>
<uses-sdk .../>
<uses-permission android:name="android.permission.WRITE_SMS"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<application
...>
...
</manifest>
Implementación:
public class SmsReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Bundle intentExtras = intent.getExtras(); if (intentExtras != null) { /* Get Messages */ Object[] sms = (Object[]) intentExtras.get("pdus"); for (int i = 0; i < sms.length; ++i) { /* Parse Each Message */ SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) sms[i]); String phone = smsMessage.getOriginatingAddress(); String message = smsMessage.getMessageBody().toString(); Toast.makeText(context, phone + ": " + message, Toast.LENGTH_SHORT).show(); } } } }
Leyendo el historial de SMS
Permisos:
<manifest ...>
<uses-sdk .../>
<uses-permission android:name="android.permission.READ_SMS"/>
<application
...>
...
</manifest>
Implementacion:
Cursor cur = getContentResolver().query(Uri.parse("content://sms/"), null, null, null, null); if (cur.moveToFirst()) { /* false = no sms */ do { String msgInfo = ""; for (int i = 0; i < cur.getColumnCount(); i++) { msgInfo += " " + cur.getColumnName(i) + ":" + cursor.getString(i); } Toast.makeText(this, msgInfo, Toast.LENGTH_SHORT).show(); } while (cursor.moveToNext()); }
Para bandeja de entrada
Sustituye content://sms/ por content://sms/inbox
Para mensajes enviados
Sustituye content://sms/ por content://sms/sent
Para borradores
Sustituye content://sms/ por content://sms/draft
Proyecto completo
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="3dp"
tools:context="${relativePackage}.${activityClass}" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:orientation="horizontal" >
<Button
android:id="@+id/btnAll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="All" />
<Button
android:id="@+id/btnInbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="3dp"
android:text="Inbox" />
<Button
android:id="@+id/btnSent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="3dp"
android:text="Sent" />
<Button
android:id="@+id/btnDraft"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="3dp"
android:text="Draft" />
</LinearLayout>
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginTop="3dp"
android:scrollbars="vertical" >
<HorizontalScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollbars="horizontal" >
<TableLayout
android:id="@+id/tblMain"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</TableLayout>
</HorizontalScrollView>
</ScrollView>
</LinearLayout>
package com.example.androidreadsms; import android.app.Activity; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.view.Gravity; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TableLayout; import android.widget.TableRow; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity implements OnClickListener { Button btnAll; Button btnInbox; Button btnSent; Button btnDraft; TableLayout tblMain; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); try { /* * Initializing Widgets */ btnAll = (Button) findViewById(R.id.btnAll); btnAll.setOnClickListener(this); btnInbox = (Button) findViewById(R.id.btnInbox); btnInbox.setOnClickListener(this); btnSent = (Button) findViewById(R.id.btnSent); btnSent.setOnClickListener(this); btnDraft = (Button) findViewById(R.id.btnDraft); btnDraft.setOnClickListener(this); tblMain = (TableLayout) findViewById(R.id.tblMain); } catch (Exception ex) { Toast.makeText(this, "Error in MainActivity.onCreate: " + ex.getMessage(), Toast.LENGTH_SHORT).show(); } } @Override public void onClick(View v) { Uri smsUri = Uri.parse("content://sms/"); switch (v.getId()) { case R.id.btnInbox: smsUri = Uri.parse("content://sms/inbox"); break; case R.id.btnSent: smsUri = Uri.parse("content://sms/sent"); break; case R.id.btnDraft: smsUri = Uri.parse("content://sms/draft"); break; } Cursor cursor = getContentResolver().query(smsUri, null, null, null, null); Cursor2TableLayout(cursor, tblMain); } public void Cursor2TableLayout(Cursor cur, TableLayout tblLayout) { /* Clearing Table If Contains Any Rows/Headers */ tblLayout.removeAllViews(); /* Moving To First */ if (!cur.moveToFirst()) { /* false = cursor is empty */ return; } /* Column Headers */ TableRow headersRow = new TableRow(this); for (int j = 0; j < cur.getColumnCount(); j++) { TextView textView = new TextView(this); textView.setGravity(Gravity.CENTER_HORIZONTAL); textView.setText(cur.getColumnName(j)); textView.setPadding(0, 0, 5, 0); textView.setAlpha(0.8f); headersRow.addView(textView); } headersRow.setPadding(10, 10, 10, 10); tblLayout.addView(headersRow); /* Rows */ for (int i = 0; i < cur.getCount(); i++) { TableRow tableRow = new TableRow(this); for (int j = 0; j < cur.getColumnCount(); j++) { TextView textView = new TextView(this); textView.setGravity(Gravity.CENTER_HORIZONTAL); textView.setText(cur.getString(j)); textView.setPadding(0, 0, 5, 0); tableRow.addView(textView); } tableRow.setPadding(10, 10, 10, 10); tblLayout.addView(tableRow); cur.moveToNext(); } cur.close(); } }