Android: escuche los mensajes SMS entrantes

Estoy tratando de crear una aplicación para monitorear los mensajes SMS entrantes, y lanzar un progtwig a través de SMS entrantes, también debe leer el contenido del SMS.

Flujo de trabajo:

  • SMS enviados a un dispositivo Android
  • aplicación autoejecutable
  • Lee la información de SMS

public class SmsListener extends BroadcastReceiver{ private SharedPreferences preferences; @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub if(intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")){ Bundle bundle = intent.getExtras(); //---get the SMS message passed in--- SmsMessage[] msgs = null; String msg_from; if (bundle != null){ //---retrieve the SMS message received--- try{ Object[] pdus = (Object[]) bundle.get("pdus"); msgs = new SmsMessage[pdus.length]; for(int i=0; i 

Nota: en su archivo de manifiesto, agregue el BroadcastReceiver-

      

Agrega este permiso:

  

Tenga en cuenta que en algunos dispositivos su código no funcionará sin android: priority = “1000” en el filtro de intención:

      

Y aquí hay algunas optimizaciones:

 public class SmsListener extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { if (Telephony.Sms.Intents.SMS_RECEIVED_ACTION.equals(intent.getAction())) { for (SmsMessage smsMessage : Telephony.Sms.Intents.getMessagesFromIntent(intent)) { String messageBody = smsMessage.getMessageBody(); } } } } 

Nota :
El valor debe ser un número entero, como “100”. Los números más altos tienen una prioridad más alta. El valor predeterminado es 0. El valor debe ser mayor que -1000 y menor que 1000.

Aquí hay un enlace.

@Mike M. y yo encontramos un problema con la respuesta aceptada (ver nuestros comentarios):

Básicamente, no tiene sentido pasar por el ciclo for si no estamos concatenando el mensaje multiparte cada vez:

 for (int i = 0; i < msgs.length; i++) { msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]); msg_from = msgs[i].getOriginatingAddress(); String msgBody = msgs[i].getMessageBody(); } 

Tenga en cuenta que simplemente establecemos msgBody en el valor de cadena de la parte respectiva del mensaje, sin importar en qué índice estemos, lo que hace que el punto de recorrer las diferentes partes del mensaje SMS sea inútil, ya que solo se configurará en el el último valor de índice En cambio, deberíamos usar += , o como señaló Mike, StringBuilder :

En general, aquí está mi código de recepción de SMS:

 if (myBundle != null) { Object[] pdus = (Object[]) myBundle.get("pdus"); // pdus is key for SMS in bundle //Object [] pdus now contains array of bytes messages = new SmsMessage[pdus.length]; for (int i = 0; i < messages.length; i++) { messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]); //Returns one message, in array because multipart message due to sms max char Message += messages[i].getMessageBody(); // Using +=, because need to add multipart from before also } contactNumber = messages[0].getOriginatingAddress(); //This could also be inside the loop, but there is no need } 

Simplemente presentando esta respuesta en caso de que alguien más tenga la misma confusión.

¡Esto es lo que usé!

 public class SMSListener extends BroadcastReceiver { // Get the object of SmsManager final SmsManager sms = SmsManager.getDefault(); String mobile,body; public void onReceive(Context context, Intent intent) { // Retrieves a map of extended data from the intent. final Bundle bundle = intent.getExtras(); try { if (bundle != null) { final Object[] pdusObj = (Object[]) bundle.get("pdus"); for (int i = 0; i < pdusObj.length; i++) { SmsMessage currentMessage = SmsMessage.createFromPdu((byte[]) pdusObj[i]); String phoneNumber = currentMessage.getDisplayOriginatingAddress(); String senderNum = phoneNumber; String message = currentMessage.getDisplayMessageBody(); mobile=senderNum.replaceAll("\\s",""); body=message.replaceAll("\\s","+"); Log.i("SmsReceiver", "senderNum: "+ senderNum + "; message: " + body); // Show Alert int duration = Toast.LENGTH_LONG; Toast toast = Toast.makeText(context, "senderNum: "+ mobile+ ", message: " + message, duration); toast.show(); } // end for loop } // bundle is null } catch (Exception e) { Log.e("SmsReceiver", "Exception smsReceiver" +e); } } } 

Si alguien se refiere a cómo hacer la misma función (leyendo OTP usando SMS recibidos) en Xamarin Android como yo:

  1. Agregue este código a su archivo AndroidManifest.xml:

             
  2. Luego crea tu clase BroadcastReveiver en tu Proyecto Android.

     [BroadcastReceiver(Enabled = true)] [IntentFilter(new[] { "android.provider.Telephony.SMS_RECEIVED" }, Priority = (int)IntentFilterPriority.HighPriority)] public class BroadcastReveiverOTP : BroadcastReceiver { public static readonly string INTENT_ACTION = "android.provider.Telephony.SMS_RECEIVED"; protected string message, address = string.Empty; public override void OnReceive(Context context, Intent intent) { if (intent.HasExtra("pdus")) { var smsArray = (Java.Lang.Object[])intent.Extras.Get("pdus"); foreach (var item in smsArray) { var sms = SmsMessage.CreateFromPdu((byte[])item); address = sms.OriginatingAddress; if (address.Equals("NotifyDEMO")) { message = sms.MessageBody; string[] pin = message.Split(' '); if (!string.IsNullOrWhiteSpace(pin[0])) { // NOTE : Here I'm passing received OTP to Portable Project using MessagingCenter. So I can display the OTP in the relevant entry field. MessagingCenter.Send(this,MessengerKeys.OnBroadcastReceived, pin[0]); } } } } } } 
  3. Registre esta clase BroadcastReceiver en su clase MainActivity en Android Project:

     public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity { // Initialize your class private BroadcastReveiverOTP _receiver = new BroadcastReveiverOTP (); protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); global::Xamarin.Forms.Forms.Init(this, bundle); LoadApplication(new App()); // Register your receiver : RegisterReceiver(_receiver, new IntentFilter("android.provider.Telephony.SMS_RECEIVED")); } } 

En caso de que desee manejar la intención de la actividad abierta, puede usar PendintIntent (Complete los siguientes pasos):

 public class SMSReciver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { final Bundle bundle = intent.getExtras(); try { if (bundle != null) { final Object[] pdusObj = (Object[]) bundle.get("pdus"); for (int i = 0; i < pdusObj.length; i++) { SmsMessage currentMessage = SmsMessage.createFromPdu((byte[]) pdusObj[i]); String phoneNumber = currentMessage.getDisplayOriginatingAddress(); String senderNum = phoneNumber; String message = currentMessage.getDisplayMessageBody(); try { if (senderNum.contains("MOB_NUMBER")) { Toast.makeText(context,"",Toast.LENGTH_SHORT).show(); Intent intentCall = new Intent(context, MainActivity.class); intentCall.putExtra("message", currentMessage.getMessageBody()); PendingIntent pendingIntent= PendingIntent.getActivity(context, 0, intentCall, PendingIntent.FLAG_UPDATE_CURRENT); pendingIntent.send(); } } catch (Exception e) { } } } } catch (Exception e) { } } } 

manifiesto:

       

onNewIntent:

  @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); Toast.makeText(this, "onNewIntent", Toast.LENGTH_SHORT).show(); onSMSReceived(intent.getStringExtra("message")); } 

Permisos: