Trabajar con SMS

Trataremos en este artículo la gestión programática de SMS. O, dicho de otro modo, veremos cómo hacer que nuestra app “lea” y envíe SMS a nuestra conveniencia.

Lectura de SMS

Preparativos

Empezaremos con la creación del proyecto. Como es habitual, será para la API 2.2 de android, pero en esta ocasión no crearemos una Activity todavía, crearemos el proyecto vacío. Una vez listo, nos iremos al AndroidManifest.xml para añadir el permiso de lectura de SMS, android.permission.RECEIVE_SMS.

Tras ello, crearemos una clase SMSReceiver (ojo, no una Activity) que heredará de BroadcastReceiver para tener así nuestro Receptor de Emisiones, la clase que leerá los SMS, en definitiva. Pero para que funcione debemos decirle a Android que esta clase es un receptor, no basta que extienda BroadcastReceiver. Para ello volvemos al AndroidManifest.xml y, en la parte inferior izquierda de la pestaña Application, añadiremos (con add) un Receiver. En Name (a la derecha), usaremos el botón browse para elegir la clase que acabamos de crear y guardamos cambios. Tras ello, arcamos el elemento que ha salido en la ventana a la izquierda (cuyo nombre será el mismo que el de nuestra clase receptora) y añadiremos de nuevo, esta vez un intent-filter. Guardamos y marcamos el intent-filter para añadir una action, la android.provider.Telephony.SMS_RECEIVED.

Con esto, nuestro receptor ya está completamente configurado para que se le llame cuando el dispositivo Android reciba SMS. Toca mancharse las manos de código.

El código

Antes de empezar con el código quizá quepa comentar que los SMS tienen varias formas de transmitirse. La que trabaja Android es el “modo PDU“. Eso quiere decir que no le llega directamente una cadena de 160 caracteres tal cual, sino una estructura PDU de la que se puede extraer, entre otras cosas, el texto del mensaje, el remitente, hora de envío, etc. Dicho esto, vamos al turrón.

Al heredar de la clase BroadcastReceiver, Eclipse nos habrá dicho que hay que implementar un método, salvo que se haya hecho desde el wizard, en cuyo caso lo habrá preparado todo para meterle el código. El método es onReceive, que recive Context e Intent como parámetros.

A este método se le pasa un array de estructuras PDU a través de las extras del Intent. Tras obtenerlas, podemos generar un array de la clase SmsMessage con cada uno.

Nota: Hay dos posibles clases SmsMessage en Android, una deprecatedo en desuso, y otra no. La que debemos usar es la android.telephony.SmsMessage.

Aquí pueden ver la clase tal cual quedaría.

Para probarlo, podemos ejecutarlo como una app normal, sólo que al no haber Activity no veremos nada. Ahora en Eclipse, iremos a Window > Open Perspective > Othery eligiremos DDMS.  Se verá algo parecido a lo que muestro en la captura:

Perspectiva DDMS

Nos interesa particularmente la columna de la izquierda, dónde se puede elegir el emulador (puede haber varios funcionando a la vez) sobre el queremos trabajar, y la pestañaemulator control, que es desde dónde podemos simular el envío de llamadas y SMS al emulador.

Con nuestro emulador resaltado, introduciremos un número de origen cualquiera, elegiremos la opción SMS y le daremos un cuerpo de mensaje. Tras ello, y teniendo a la vista la ventana del emulador, le daremos al botón Send para su envío y veremos lo que ocurre en el emulador.Perspectiva DDMS

Nos interesa particularmente la columna de la izquierda, dónde se puede elegir el emulador (puede haber varios funcionando a la vez) sobre el queremos trabajar, y la pestaña emulator control, que nos permite simular el envío de llamadas y/o SMS al emulador señalado.

Resaltamos nuestro emulador (que habremos invocado al ejecutar el proyecto), introduciremos un número remitente cualquiera, elegiremos la opción de SMS e introduciremos un cuerpo de mensaje. Tras hacerlo, pondremos la ventana del emulador a la vista y enviaremos el SMS con el botón Send. En nuestro emulador nos debe salir un emergente tipo Toast con la información del mensaje.

Envío de SMS

Preparativos

Para el envío de SMS necesitamos un permiso adicional: android.permission.SEND_SMS.

Añadido el permiso, crearemos una Activity llamada EnviaMensaje. Tras crearla, procederemos a registrarla en el AndroidManifest. En la pestaña application, dónde configuramos nuestro receptor, pulsaremos Add asegurándonos de que no haya nada resaltado en la ventana de la izquierda. Añadiremos una Activity cuyo nombre será el de nuestra Actividad, pero con un “.” delante, en nuestro caso, “.EnviaMensaje”, para que Android sepa que dicha clase está dentro de nuestro paquete com.alberovalley.smstutorial. Podemos darle también una etiqueta o label tal como @string/app_name. Resaltando nuestra actividad, añadiremos, esta vez, un intent-filter que contendrá una action y una category. La action será la android.intent.action.MAIN, la category la android.intent.category.LAUNCHER. Acabamos de registrar la actividad como launcher/main, o sea, que será la que se ejecute cuando el usuario llame a nuestra aplicación.

Nota: A los Intents, o formas de invocar las Activities, se les puede asociar una acción, unos datos y una categoría. Las actividades pueden declarar el tipo de acciones que pueden llevar a cabo y los tipos de datos que pueden gestionar. Las acciones son cadenas de texto estándar que describen lo que que la actividad puede hacer. Por ejemplo, android.intent.action.VIEW es una acción que indica que la actividad puede mostrar datos al usuario. Esta acción viene predefinida en la clase Intent, pero es posible definir nuevas acciones para nuestras actividades. La misma actividad puede declarar que el tipo de datos del que se ocupa es, por ejemplo, “vnd.android.cursor.dir/person”. También puede declarar una categoría, que básicamente indica si la actividad va a ser lanzada desde el lanzador de aplicaciones, desde el menú de otra aplicación o directamente desde otra actividad.

Todo esto que hemos hecho ahora es lo que hace automáticamente el wizard de Eclipse cuando, durante la creación del proyecto, le decimos que queremos que cree una Activity.

Necesitaremos en el layout dos TextView para indicar el número al que queremos enviar el SMS y el propio texto del SMS; así como un botón para lanzar el mensaje. El layout – podemos hacerlo sobre el propio main.xml que viene por defecto – quedaría como éste.

El código.

Ya en el código de la Activity, asociamos los elementos de la interfaz a variables de clase como es habitual. Implementamos la interfaz OnClickListener para capturar el evento del botón y en ella llamaremos a una función que recibirá el número de teléfono y el texto del mensaje y se encargará del envío del mismo. Aquí el código necesario para el envío de mensajes:

private void sendSMS(String phoneNumber, String message)
    {
        PendingIntent pi = PendingIntent.getActivity(this, 0,
            new Intent(this, EnviaMensaje.class), 0);
        SmsManager sms = SmsManager.getDefault();
        sms.sendTextMessage(phoneNumber, null, message, pi, null);
    }

Todo lo que nos resta ahora es probarlo. Para ver que funciona bien, debemos tener activos dos emuladores, uno en el que se instalará nuestra aplicación y otro para que sirva de receptor. El primero saldrá automáticamente al ejecutar el proyecto, el segundo lo podemos iniciar nosotros mismos desde el botón AVD Manager. Cuando estén ambos abiertos y listos, vamos a nuestra app y metemos como número de teléfono el puerto del otro emulador. El puerto lo localizaremos arriba a la izquierda de la ventana, normalmente en formato XXXX:y.z, siendo XXXX el que debemos usar. En mi caso el receptor tiene el 5556:2.2 (puerto 5556, API 2.2), así que en mi app introduciré 5556 como número de teléfono destinatario y el texto del sms.

Envío de SMS entre AVDs

Envío de SMS entre AVDs

Aviso: Los SMS no deben tener una longitud superior a 160. Si la longitud de la cadena message supera esa cifra, la aplicación fallará (yo he intentado atrapar cualquier excepción en el envío de SMS de longitudes superiores, pero nunca ocurre). Se recomienda, pues, que se desarrolle un algoritmo que divida el mensaje en varios trozos y los envíe sucesivamente si es necesario que el mensaje sea mas largo de 160 caracteres.

Cómo es habitual, dejo enlace al repo dónde está todo el código de este tutorial aquí.

PD: Una mención especial al blog javiercancela.com, de dónde obtuve la explicación mas clara y sencilla que hallé sobre los intent-filters.

About these ads

Un Comentario to “Trabajar con SMS”

Deja un comentario

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

Seguir

Recibe cada nueva publicación en tu buzón de correo electrónico.

Únete a otros 176 seguidores

%d personas les gusta esto: