¿Cómo puedo leer mensajes SMS desde el dispositivo mediante programación en Android?

249

¿Quiero recuperar los mensajes SMS del dispositivo y mostrarlos?

Manoj Perumarath
fuente
@David Freitas Enlace de confianza +1
Shahzad Imam
3
@DavidFreitas este enlace no funciona, ¿podría compartir el último enlace?
Khobaib
3
@Khobaib, como siempre, las cosas en Internet son fugaces. Encontré una copia en archive.org stackoverflow.com/a/19966227/40961 , gracias a Dios por ellos (he donado recientemente para mantenerlos en funcionamiento). Pero deberíamos considerar convertir el contenido de la página de web.archive.org/web/20121022021217/http://mobdev.olin.edu/… a la sintaxis de reducción en una respuesta a esta pregunta. Probablemente una hora de trabajo.
David d C e Freitas

Respuestas:

157

Use Content Resolver ( "content: // sms / inbox" ) para leer los SMS que están en la bandeja de entrada.

// public static final String INBOX = "content://sms/inbox";
// public static final String SENT = "content://sms/sent";
// public static final String DRAFT = "content://sms/draft";
Cursor cursor = getContentResolver().query(Uri.parse("content://sms/inbox"), null, null, null, null);

if (cursor.moveToFirst()) { // must check the result to prevent exception
    do {
       String msgData = "";
       for(int idx=0;idx<cursor.getColumnCount();idx++)
       {
           msgData += " " + cursor.getColumnName(idx) + ":" + cursor.getString(idx);
       }
       // use msgData
    } while (cursor.moveToNext());
} else {
   // empty box, no SMS
}

Por favor agregue READ_SMS permiso.

Espero que ayude :)

Suryavel TR
fuente
77
¡Gracias! Escribiste mal "getColumnName", de lo contrario, funciona de maravilla. Ah, y si alguien va a usar esto, no olvides agregar el permiso android.permission.READ_SMS.
qwerty
1
Gracias. Lo modifiqué :)
Suryavel TR
55
¿Esto también utiliza la API indocumentada que @CommonsWare especificó en su comentario a la respuesta aceptada?
Krishnabhadra
1
¡Atención! No te pierdas moveToFirstcomo yo lo hice.
Alexandr Priymak
44
@ Krishnabhadra Sí. Utiliza el proveedor de contenido indocumentado "content: // sms / inbox".
pm_labs
79
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        final String myPackageName = getPackageName();
        if (!Telephony.Sms.getDefaultSmsPackage(this).equals(myPackageName)) {

            Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
            intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, myPackageName);
            startActivityForResult(intent, 1);
        }else {
            List<Sms> lst = getAllSms();
        }
    }else {
        List<Sms> lst = getAllSms();
    }

Establecer aplicación como aplicación de SMS predeterminada

    @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) {
    if (resultCode == RESULT_OK) {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            final String myPackageName = getPackageName();
            if (Telephony.Sms.getDefaultSmsPackage(mActivity).equals(myPackageName)) {

                List<Sms> lst = getAllSms();
            }
        }
    }
}
}

Función para recibir SMS

public List<Sms> getAllSms() {
    List<Sms> lstSms = new ArrayList<Sms>();
    Sms objSms = new Sms();
    Uri message = Uri.parse("content://sms/");
    ContentResolver cr = mActivity.getContentResolver();

    Cursor c = cr.query(message, null, null, null, null);
    mActivity.startManagingCursor(c);
    int totalSMS = c.getCount();

    if (c.moveToFirst()) {
        for (int i = 0; i < totalSMS; i++) {

            objSms = new Sms();
            objSms.setId(c.getString(c.getColumnIndexOrThrow("_id")));
            objSms.setAddress(c.getString(c
                    .getColumnIndexOrThrow("address")));
            objSms.setMsg(c.getString(c.getColumnIndexOrThrow("body")));
            objSms.setReadState(c.getString(c.getColumnIndex("read")));
            objSms.setTime(c.getString(c.getColumnIndexOrThrow("date")));
            if (c.getString(c.getColumnIndexOrThrow("type")).contains("1")) {
                objSms.setFolderName("inbox");
            } else {
                objSms.setFolderName("sent");
            }

            lstSms.add(objSms);
            c.moveToNext();
        }
    }
    // else {
    // throw new RuntimeException("You have no SMS");
    // }
    c.close();

    return lstSms;
}

La clase de SMS está abajo:

public class Sms{
private String _id;
private String _address;
private String _msg;
private String _readState; //"0" for have not read sms and "1" for have read sms
private String _time;
private String _folderName;

public String getId(){
return _id;
}
public String getAddress(){
return _address;
}
public String getMsg(){
return _msg;
}
public String getReadState(){
return _readState;
}
public String getTime(){
return _time;
}
public String getFolderName(){
return _folderName;
}


public void setId(String id){
_id = id;
}
public void setAddress(String address){
_address = address;
}
public void setMsg(String msg){
_msg = msg;
}
public void setReadState(String readState){
_readState = readState;
}
public void setTime(String time){
_time = time;
}
public void setFolderName(String folderName){
_folderName = folderName;
}

}

No olvides definir el permiso en tu AndroidManifest.xml

<uses-permission android:name="android.permission.READ_SMS" />
Atif Mahmood
fuente
2
Esa es una buena pieza de código. Solo una cosa, el tiempo se obtiene en milisegundos. Creo que será mejor que sea un formato legible para humanos comoString receiveDayTime = Functions.dateFromMilisec(Long.valueOf(c.getColumnIndexOrThrow("date")), "hh:mm a MMM dd, yyyy");
Bibaswann Bandyopadhyay
1
¿cuál es el propósito de hacer todo con get y set, yo realmente no entiendo por qué no sólo tiene que utilizar una matriz asociativa o clase cuyos elementos se accede directamente
michnovka
1
@TomasNavara: Consulte este código para comprender el uso de getter y setter. pastebin.com/Nh8YXtyJ
errores ocurren el
@BibaswannBandyopadhyay Si no quieres usar nada excepto las bibliotecas de Android y las bibliotecas de Java. new SimpleDateFormat("hh:mm", Locale.US).format(new Date(Long.parseLong(_time)));Esto te dará 24 horas de tiempo.
Chris - Jr
mActivityno está definido. ¿Que es esto?
dthree
61

Es un proceso trivial. Puedes ver un buen ejemplo en el código fuente SMSPopup

Examine los siguientes métodos:

SmsMmsMessage getSmsDetails(Context context, long ignoreThreadId, boolean unreadOnly)
long findMessageId(Context context, long threadId, long _timestamp, int messageType
void setMessageRead(Context context, long messageId, int messageType)
void deleteMessage(Context context, long messageId, long threadId, int messageType)

Este es el método de lectura:

SmsMmsMessage getSmsDetails(Context context,
                            long ignoreThreadId, boolean unreadOnly)
{
   String SMS_READ_COLUMN = "read";
   String WHERE_CONDITION = unreadOnly ? SMS_READ_COLUMN + " = 0" : null;
   String SORT_ORDER = "date DESC";
   int count = 0;
   // Log.v(WHERE_CONDITION);
   if (ignoreThreadId > 0) {
      // Log.v("Ignoring sms threadId = " + ignoreThreadId);
      WHERE_CONDITION += " AND thread_id != " + ignoreThreadId;
   }
   Cursor cursor = context.getContentResolver().query(
                      SMS_INBOX_CONTENT_URI,
                      new String[] { "_id", "thread_id", "address", "person", "date", "body" },
                      WHERE_CONDITION,
                      null,
                      SORT_ORDER);
   if (cursor != null) {
      try {
         count = cursor.getCount();
         if (count > 0) {
            cursor.moveToFirst();
            // String[] columns = cursor.getColumnNames();
            // for (int i=0; i<columns.length; i++) {
            // Log.v("columns " + i + ": " + columns[i] + ": " + cursor.getString(i));
            // }                                         
            long messageId = cursor.getLong(0);
            long threadId = cursor.getLong(1);
            String address = cursor.getString(2);
            long contactId = cursor.getLong(3);
            String contactId_string = String.valueOf(contactId);
            long timestamp = cursor.getLong(4);

            String body = cursor.getString(5);                             
            if (!unreadOnly) {
                count = 0;
            }

            SmsMmsMessage smsMessage = new SmsMmsMessage(context, address,
                          contactId_string, body, timestamp,
                          threadId, count, messageId, SmsMmsMessage.MESSAGE_TYPE_SMS);
            return smsMessage;
         }
      } finally {
         cursor.close();
      }
   }               
   return null;
}
Ömer
fuente
47
Esto no es parte del SDK de Android. Este código supone incorrectamente que todos los dispositivos son compatibles con este proveedor de contenido no documentado y no compatible. Google ha indicado explícitamente que confiar en esto no es una buena idea: android-developers.blogspot.com/2010/05/…
CommonsWare
1
@ Janusz: No hay medios documentados y compatibles que funcionen en todos los clientes de SMS en todos los dispositivos.
CommonsWare
99
@CommonsWare que es triste de escuchar. Puede que tenga que vivir con esta API entonces.
Janusz
@Omer ¿Alguna idea de cómo contaría la cantidad de mensajes SMS por contacto?
SpicyWeenie
44
El código se ha movido. Al buscar SmsPopupUtils.java me conseguí un nuevo enlace en el código de Google. En caso de que lo muevan nuevamente o lo descontinúen por completo, aquí hay un enlace de respaldo: pastebin.com/iPt7MLyM
KalEl
25

Desde API 19 en adelante, puede hacer uso de la Clase de telefonía para eso; Dado que los valores codificados no recuperarán mensajes en todos los dispositivos porque el proveedor de contenido Uri cambia de dispositivos y fabricantes.

public void getAllSms(Context context) {

    ContentResolver cr = context.getContentResolver();
    Cursor c = cr.query(Telephony.Sms.CONTENT_URI, null, null, null, null);
    int totalSMS = 0;
    if (c != null) {
        totalSMS = c.getCount();
        if (c.moveToFirst()) {
            for (int j = 0; j < totalSMS; j++) {
                String smsDate = c.getString(c.getColumnIndexOrThrow(Telephony.Sms.DATE));
                String number = c.getString(c.getColumnIndexOrThrow(Telephony.Sms.ADDRESS));
                String body = c.getString(c.getColumnIndexOrThrow(Telephony.Sms.BODY));
                Date dateFormat= new Date(Long.valueOf(smsDate));
                String type;
                switch (Integer.parseInt(c.getString(c.getColumnIndexOrThrow(Telephony.Sms.TYPE)))) {
                    case Telephony.Sms.MESSAGE_TYPE_INBOX:
                        type = "inbox";
                        break;
                    case Telephony.Sms.MESSAGE_TYPE_SENT:
                        type = "sent";
                        break;
                    case Telephony.Sms.MESSAGE_TYPE_OUTBOX:
                        type = "outbox";
                        break;
                    default:
                        break;
                }


                c.moveToNext();
            }
        }

        c.close();

    } else {
        Toast.makeText(this, "No message to show!", Toast.LENGTH_SHORT).show();
    }
}
Manoj Perumarath
fuente
99
Parece ser la única respuesta que no utiliza API indocumentada y no se refiere a bibliotecas de terceros.
Ishamael
Intenté usar este código para recibir mensajes SMS de Hangouts (que es mi aplicación de SMS predeterminada). En cambio, recuperó el último mensaje saliente que envié a través de Messenger ... ¿Sabes qué está causando esto?
Miki P
@MikiP usando mis poderes de adivinanza, diré que la aplicación Messenger te preguntó acerca de cómo reemplazar la administración de SMS con Messenger. Sucede con alguna otra aplicación de mensajería. No tengo otra explicación.
m3nda
2
No olvides llamar a c.close ();
Cícero Moura
1
@SardarAgabejli Si usamos valores codificados como "contenturi: sms", no será lo mismo para todos los dispositivos, pero si usamos la clase de telefonía, obtendremos acceso directo a esa uri o la ruta de sms db de ese dispositivo, es una clase auxiliar para señalar el db de sms
Manoj Perumarath
23

Esta publicación es un poco antigua, pero aquí hay otra solución fácil para obtener datos relacionados con SMS proveedor de contenido en Android:

Use esta biblioteca: https://github.com/EverythingMe/easy-content-providers

  • Obtén todo SMS:

    TelephonyProvider telephonyProvider = new TelephonyProvider(context);
    List<Sms> smses = telephonyProvider.getSms(Filter.ALL).getList();

    Cada SMS tiene todos los campos, por lo que puede obtener cualquier información que necesite:
    dirección, cuerpo, fecha de recepción, tipo (INBOX, SENT, DRAFT, ..), threadId, ...

  • Gel todo MMS:

    List<Mms> mmses = telephonyProvider.getMms(Filter.ALL).getList();
  • Gel todo Thread:

    List<Thread> threads = telephonyProvider.getThreads().getList();
  • Gel todo Conversation:

    List<Conversation> conversations = telephonyProvider.getConversations().getList();

Funciona con Listo Cursory hay una aplicación de muestra para ver cómo se ve y funciona.

De hecho, hay un soporte para todos los proveedores de contenido de Android como: Contactos, Registros de llamadas, Calendario, ... Documento completo con todas las opciones: https://github.com/EverythingMe/easy-content-providers/wiki/Android- proveedores

Espero que también haya ayudado :)

Sromku
fuente
1
El código fuente y los ejemplos en el github son bastante útiles. Este es un buen contenedor / fachada para los proveedores más comunes. Gracias.
m3nda
14

Paso 1: primero tenemos que agregar permisos en el archivo de manifiesto como

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

Paso 2: luego agregue la clase de receptor de sms de servicio para recibir sms

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

Paso 3: Agregar permiso de tiempo de ejecución

private boolean checkAndRequestPermissions()
{
    int sms = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_SMS);

    if (sms != PackageManager.PERMISSION_GRANTED)
    {
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_SMS}, REQUEST_ID_MULTIPLE_PERMISSIONS);
        return false;
    }
    return true;
}

Paso 4: Agregue estas clases en su aplicación y pruebe la clase de interfaz

public interface SmsListener {
   public void messageReceived(String messageText);
}

SmsReceiver.java

public class SmsReceiver extends BroadcastReceiver {
private static SmsListener mListener;
public Pattern p = Pattern.compile("(|^)\\d{6}");
@Override
public void onReceive(Context context, Intent intent) {
    Bundle data  = intent.getExtras();
    Object[] pdus = (Object[]) data.get("pdus");
    for(int i=0;i<pdus.length;i++)
    {
        SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) pdus[i]);
        String sender = smsMessage.getDisplayOriginatingAddress();
        String phoneNumber = smsMessage.getDisplayOriginatingAddress();
        String senderNum = phoneNumber ;
        String messageBody = smsMessage.getMessageBody();
        try
        {
  if(messageBody!=null){
   Matcher m = p.matcher(messageBody);
    if(m.find()) {
      mListener.messageReceived(m.group(0));  }
 else {}}  }
        catch(Exception e){} } }
public static void bindListener(SmsListener listener) {
    mListener = listener; }}
Venkatesh
fuente
¿Qué hace el patrón?
Mark Buikema
Bueno ... ¿es ese ("com.aquadeals.seller.services.SmsReceiver") el nombre común del servicio?
m3nda
Sí, ese no es el nombre del servicio, esa es la ruta de clase SmsReceiver en mi aplicación
Venkatesh
¿Por qué necesita permiso para LOCATION?
Zam hundido el
1
Estoy tratando de hacer una aplicación que muestre el contenido de SMS al usuario incluso si la aplicación ha sido eliminada
Anjani Mittal
11

Ya hay muchas respuestas disponibles, pero creo que a todas ellas les falta una parte importante de esta pregunta. Antes de leer los datos de una base de datos interna o su tabla, debemos comprender cómo se almacenan los datos en ella y luego podemos encontrar la solución de la pregunta anterior que es:

¿Cómo puedo leer mensajes SMS desde el dispositivo mediante programación en Android?

Entonces, en la tabla de SMS de Android es como se ve así

ingrese la descripción de la imagen aquí

Sabe, podemos seleccionar lo que queramos de la base de datos. En nuestro caso solo hemos requerido

identificación, dirección y cuerpo

En caso de leer SMS:

1. Pida permisos

int REQUEST_PHONE_CALL = 1;

   if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_SMS) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_SMS}, REQUEST_PHONE_CALL);
        }

o

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

2. Ahora su código va así

// Create Inbox box URI
Uri inboxURI = Uri.parse("content://sms/inbox");

// List required columns
String[] reqCols = new String[]{"_id", "address", "body"};

// Get Content Resolver object, which will deal with Content Provider
ContentResolver cr = getContentResolver();

// Fetch Inbox SMS Message from Built-in Content Provider
Cursor c = cr.query(inboxURI, reqCols, null, null, null);

// Attached Cursor with adapter and display in listview
adapter = new SimpleCursorAdapter(this, R.layout.a1_row, c,
        new String[]{"body", "address"}, new int[]{
        R.id.A1_txt_Msg, R.id.A1_txt_Number});
lst.setAdapter(adapter);

Espero que este sea útil. Gracias.

Nitin Khanna
fuente
7

Los servicios de Google Play tienen dos API que puede usar para optimizar el proceso de verificación basado en SMS

API de recuperación de SMS

Proporciona una experiencia de usuario totalmente automatizada, sin requerir que el usuario escriba manualmente códigos de verificación y sin requerir ningún permiso adicional de la aplicación y debe usarse cuando sea posible. Sin embargo, requiere que coloque un código hash personalizado en el cuerpo del mensaje, por lo que también debe tener control sobre el lado del servidor .

  • Requisitos de mensajes : código hash de 11 dígitos que identifica de forma exclusiva su aplicación
  • Requisitos del remitente : ninguno
  • Interacción del usuario : ninguna

Solicitar verificación de SMS en una aplicación de Android

Realizar verificación de SMS en un servidor

API de consentimiento de usuario de SMS

No requiere el código hash personalizado, sin embargo, requiere que el usuario apruebe la solicitud de su aplicación para acceder al mensaje que contiene el código de verificación. Para minimizar las posibilidades de que el usuario muestre un mensaje incorrecto, SMS User Consentfiltrará los mensajes de los remitentes en la lista de Contactos del usuario.

  • Requisitos de mensaje : código alfanumérico de 4 a 10 dígitos que contiene al menos un número
  • Requisitos del remitente : el remitente no puede estar en la lista de contactos del usuario
  • Interacción del usuario : un toque para aprobar

The SMS User Consent APIforma parte de los servicios de Google Play. Para usarlo, necesitará al menos la versión 17.0.0de estas bibliotecas:

implementation "com.google.android.gms:play-services-auth:17.0.0"
implementation "com.google.android.gms:play-services-auth-api-phone:17.1.0"

Paso 1: Comience a escuchar mensajes SMS

El consentimiento del usuario de SMS escuchará los mensajes SMS entrantes que contengan un código único durante un máximo de cinco minutos. No verá ningún mensaje que se envíe antes de que comience. Si conoce el número de teléfono que enviará el código de una sola vez, puede especificar el senderPhoneNumber, o si no null, coincidirá con cualquier número.

 smsRetriever.startSmsUserConsent(senderPhoneNumber /* or null */)

Paso 2: Solicite consentimiento para leer un mensaje

Una vez que su aplicación recibe un mensaje que contiene un código único, se le notificará por una transmisión. En este punto, no tiene consentimiento para leer el mensaje; en su lugar, se le otorga un Intentmensaje que puede comenzar a solicitar al usuario para obtener su consentimiento. Dentro de su BroadcastReceiver, muestra el mensaje utilizando Intentel extras. Cuando comience esa intención, solicitará al usuario permiso para leer un solo mensaje. Se les mostrará el texto completo que compartirán con su aplicación.

val consentIntent = extras.getParcelable<Intent>(SmsRetriever.EXTRA_CONSENT_INTENT)
startActivityForResult(consentIntent, SMS_CONSENT_REQUEST)

ingrese la descripción de la imagen aquí

Paso 3: Analice el código único y complete la verificación por SMS

Cuando el usuario hace clic “Allow”, ¡es hora de leer el mensaje! Dentro de onActivityResultusted puede obtener el texto completo del mensaje SMS de los datos:

val message = data.getStringExtra(SmsRetriever.EXTRA_SMS_MESSAGE)

¡Luego analiza el mensaje SMS y pasa el código único a tu backend!

Levon Petrosyan
fuente
4-10 digit alphanumeric code containing at least one number¿Puedes explicar qué significa eso? ¿Significa que la longitud del mensaje completo debe ser de 4 a 10 caracteres solo del código sms?
Zeeshan Shabbir
Gracias también
Levon Petrosyan
Esto funciona solo para la verificación OTP ¿verdad? ¿Qué pasa con la lectura de todos los demás mensajes dentro del teléfono, todos los SMS, etc.? ¿Hay alguna nueva API para eso? Avísame. ¡Feliz codificación! :)
Manoj Perumarath
Siempre tenemos el error de tiempo de espera. Por favor, ayúdame
Manikandan K
2
String WHERE_CONDITION = unreadOnly ? SMS_READ_COLUMN + " = 0" : null;

cambiado por:

String WHERE_CONDITION = unreadOnly ? SMS_READ_COLUMN + " = 0 " : SMS_READ_COLUMN + " = 1 ";
Van Hau Hoang
fuente
2

Código de Kotlin para leer SMS:

1- Agregue este permiso a AndroidManifest.xml:

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

2-Crear una clase de receptor BroadCast:

package utils.broadcastreceivers

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.telephony.SmsMessage
import android.util.Log

class MySMSBroadCastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
    var body = ""
    val bundle = intent?.extras
    val pdusArr = bundle!!.get("pdus") as Array<Any>
    var messages: Array<SmsMessage?>  = arrayOfNulls(pdusArr.size)

 // if SMSis Long and contain more than 1 Message we'll read all of them
    for (i in pdusArr.indices) {
        messages[i] = SmsMessage.createFromPdu(pdusArr[i] as ByteArray)
    }
      var MobileNumber: String? = messages[0]?.originatingAddress
       Log.i(TAG, "MobileNumber =$MobileNumber")         
       val bodyText = StringBuilder()
        for (i in messages.indices) {
            bodyText.append(messages[i]?.messageBody)
        }
        body = bodyText.toString()
        if (body.isNotEmpty()){
       // Do something, save SMS in DB or variable , static object or .... 
                       Log.i("Inside Receiver :" , "body =$body")
        }
    }
 }

3-Obtenga permiso de SMS si Android 6 y superior:

   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && 
    ActivityCompat.checkSelfPermission(context!!,
            Manifest.permission.RECEIVE_SMS
        ) != PackageManager.PERMISSION_GRANTED
    ) { // Needs permission

            requestPermissions(arrayOf(Manifest.permission.RECEIVE_SMS),
            PERMISSIONS_REQUEST_READ_SMS
        )

    } else { // Permission has already been granted

    }

4- Agregue este código de solicitud a la Actividad o fragmento:

 companion object {
    const val PERMISSIONS_REQUEST_READ_SMS = 100
   }

5- Anulación de verificación de permisos Solicitar resultado divertido:

 override fun onRequestPermissionsResult(
    requestCode: Int, permissions: Array<out String>,
    grantResults: IntArray
) {
    when (requestCode) {

        PERMISSIONS_REQUEST_READ_SMS -> {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Log.i("BroadCastReceiver", "PERMISSIONS_REQUEST_READ_SMS Granted")
            } else {
                //  toast("Permission must be granted  ")
            }
        }
    }
}
Hamed Jaliliani
fuente
1

La función más fácil

Para leer el sms escribí una función que devuelve un objeto de conversación:

class Conversation(val number: String, val message: List<Message>)
class Message(val number: String, val body: String, val date: Date)

fun getSmsConversation(context: Context, number: String? = null, completion: (conversations: List<Conversation>?) -> Unit) {
        val cursor = context.contentResolver.query(Telephony.Sms.CONTENT_URI, null, null, null, null)

        val numbers = ArrayList<String>()
        val messages = ArrayList<Message>()
        var results = ArrayList<Conversation>()

        while (cursor != null && cursor.moveToNext()) {
            val smsDate = cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Sms.DATE))
            val number = cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Sms.ADDRESS))
            val body = cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Sms.BODY))

            numbers.add(number)
            messages.add(Message(number, body, Date(smsDate.toLong())))
        }

        cursor?.close()

        numbers.forEach { number ->
            if (results.find { it.number == number } == null) {
                val msg = messages.filter { it.number == number }
                results.add(Conversation(number = number, message = msg))
            }
        }

        if (number != null) {
            results = results.filter { it.number == number } as ArrayList<Conversation>
        }

        completion(results)
    }

Utilizando:

getSmsConversation(this){ conversations ->
    conversations.forEach { conversation ->
        println("Number: ${conversation.number}")
        println("Message One: ${conversation.message[0].body}")
        println("Message Two: ${conversation.message[1].body}")
    }
}

O obtenga solo una conversación de un número específico:

getSmsConversation(this, "+33666494128"){ conversations ->
    conversations.forEach { conversation ->
        println("Number: ${conversation.number}")
        println("Message One: ${conversation.message[0].body}")
        println("Message Two: ${conversation.message[1].body}")
    }
}
Mickael Belhassen
fuente