Interceptar SMS desde una librería.

IncomingSMSNo hace mucho expliqué como se podían interceptar llamadas entrantes desde una aplicación Android.

Para recibir mensajes entrantes únicamente se deberían modificar algunos parámetros tal y como explica Karam Balkar en su blog.

Pero como se pueden realizar este tipo de intercepciones desde una librería que se carga desde tu aplicación.

Para empezar crearemos una librería cuyo propósito es interceptar mensajes SMS y mostrarlos por pantalla cuyo nombre será receiversms.

La librería tendrá una única clase MainLibrary, que extenderá de FrameLayout, que nos permitirá incluir la clase como un widget de android dentro del Activity que la utilizará.

 


package es.tutorial.receiversms;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.telephony.SmsMessage;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import java.util.Random;

public class MainLibrary extends FrameLayout {

Context context = null;
TextView mensaje;

Implementamos los constructores necesarios de FrameLayout.
En los tres constructores realizaremos lo mismo:

  • Definir la propiedad context para poderla utilizar en otros métodos.
  • Llamar al método populate para construir la pantalla.
  • Definir el registerReceiver para interceptar los SMS entrantes.
public MainLibrary (Context context) {
// Inflate the menu; this adds items to the action bar if it is present.
super(context);
this.context = context;
this.populate(context);
context.registerReceiver(receiver, new IntentFilter("android.provider.Telephony.SMS_RECEIVED"));
}

public MainLibrary (Context context, AttributeSet attrs, int defStyle) {
// Inflate the menu; this adds items to the action bar if it is present.
super(context);
this.context = context;
this.populate(context);
context.registerReceiver(receiver, new IntentFilter("android.provider.Telephony.SMS_RECEIVED"));
}

public MainLibrary (Context context, AttributeSet attrs) {
// Inflate the menu; this adds items to the action bar if it is present.
super(context);
this.context = context;
this.populate(context);
context.registerReceiver(receiver, new IntentFilter("android.provider.Telephony.SMS_RECEIVED"));
}

El método populate definirá un RelativeLayout que contendrá un TextView donde se mostrará el contenido del SMS recibido.

private void populate (Context context) {
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
RelativeLayout layout = new RelativeLayout(context);
layout.setLayoutParams(layoutParams);

layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
mensaje = new TextView(context);
mensaje.setLayoutParams(layoutParams);
mensaje.setId(new Random().nextInt());

layout.addView(mensaje);
this.addView(layout);
}

Se define el BroadcastReceiver que realizará la intercepción del SMS, leera el mensaje entrante y mostrará su contenido por pantalla.

/**
* Incerceptor de mensajes recibidos.
*/
BroadcastReceiver receiver = new BroadcastReceiver()
{
@Override
public void onReceive(Context context, Intent intent)
{
if(intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")){
// Standard decoding for SMS
Object[] pdus = (Object[])intent.getExtras().get("pdus");
StringBuilder message = new StringBuilder();
SmsMessage messageSegment;

for (int i=0;i < pdus.length;i++)
{
messageSegment = SmsMessage.createFromPdu((byte[]) pdus[i]);
message.append(messageSegment.getDisplayMessageBody());
}
if (isMessageValid(message.toString()))
{
mensaje.setText(message.toString());
}
}
}

El método isMessageValid servirá para definir aquellos mensajes que se quieren mostrar. En nuestro caso se mostrarán todos.

/**
* Valida si el mensaje recibido se ajusta al patron definido como mensaje con PIN.
* @param message mensaje recibido
* @return true cuando el mensaje se ajusta al patron. false cuando no se ajusta.
*/
private boolean isMessageValid(String message)
{
// Implementar si el mensaje es el que queremos
return true;
}
};
}

Una vez creada la librería crearemos la aplicación Android que llamaremos app. La aplicación la he a partir de un Black Activity de Android Studio.

Añadimos la dependencia de la aplicación para que pueda utilizar la librería. Para ello se pulsa el botón derecho sobre el nombre del módulo y se selecciona la opción Open Module Settings abriendose la pantallla de Project Structure, desde la pestaña Dependencies se podrá añadir la librería.

DependenciasLibreria

Se modifica el fichero AndroidManifest.xml para añadir los permisos para interceptar la recepción de SMS y la lectura de SMS.

<pre><?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="es.tutorial.incomingsms" >

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest></pre>

Se modifica el layout activity_main.xml para incluir la librería y un botón en la parte inferior.

<pre><RelativeLayout 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:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">
    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/viewBottom"
        android:layout_alignParentBottom="true"
        >
        <Button
            android:text="@string/hello_world2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/mensajefinal" />
    </RelativeLayout>
    <es.tutorial.receiversms.MainLibrary
        android:id="@+id/view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="left"
        android:background="#507AAA"
        android:layout_margin="5dp"
        android:layout_above="@id/viewBottom"
        >

    </es.tutorial.receiversms.MainLibrary>
</RelativeLayout></pre>

Y para finalizar modificaremos el método onCreate la clase MainActivity para instanciar la clase MainLibrary por si se quisiera incluir alguna parametrización desde la aplicación.

<pre>protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    MainLibrary mainLibrary = new MainLibrary(this.getApplicationContext());

    Button mensajefinal = (Button) findViewById(R.id.mensajefinal);

    mensajefinal.setOnClickListener(new View.OnClickListener()
    {
        public void onClick(View v)
        {

        }
    });
}

Para probar el funcionamiento se podrá hacer enviando un Android Virtual Device y enviando un mensaje desde el Android Device Monitor.
ADM_simularSMS

Se puede descargar el código desde mi repositorio de github.

Espero que os sirva y os sea útil.

img_ccTodo el material publicado en este Blog, salvo las obras que no pertenecen a su autor, se difunden bajo licencia CC by-SA de Creative Commons, por lo que eres libre de copiar, distribuir y comunicar este contenido de forma publica, hacer un uso comercial del mismo, etc., siempre que lo hagas bajo las condiciones de la licencia indicada, y que reconozcas a su autor e indiques un enlace al contenido original o en su defecto a la pagina principal de este blog.

Anuncios
  1. No trackbacks yet.

Responder

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

A %d blogueros les gusta esto: