BroadcastReceiver no funciona después de BOOT_COMPLETED
Estoy tratando de interceptar SMS entrantes después de boot_completado pero estoy teniendo un problema con una NullPointerException en esta línea:
Object[] rawMsgs=(Object[])intent.getExtras().get("pdus");
Aquí está mi manifiesto:
- Detectar qué tarjeta SIM ha recibido el mensaje
- ¿Es possilbe leer y / o modificar la cabecera de SMS en Android?
- La intención de la aplicación sms no funciona en android 3.0 y superior
- Android: obtenga la hora de la fecha de la marca de tiempo de SMS en milisegundos
- Android: ¿Cómo registrar un observador de contenido sin actividad?
<uses-permission android:name="android.permission.SEND_SMS"></uses-permission> <uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses- permission> <uses-permission android:name="android.permission.INTERNET"></uses-permission> <uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <application android:icon="@drawable/icon" android:label="@string/app_name" android:theme="@android:style/Theme.NoTitleBar"> <receiver android:name=".SMSReceiver" android:permission="android.permission.BROADCAST_SMS" > <intent-filter android:priority="1000"> <action android:name="android.provider.Telephony.SMS_RECEIVED"></action> <action android:name="android.intent.action.BOOT_COMPLETED"></action> </intent-filter> </receiver> </application>
Receptor:
public class SMSReceiver extends BroadcastReceiver { private final LocationListener locationListener = new LocationListener() { public void onLocationChanged(Location location) { } public void onProviderDisabled(String provider){} public void onProviderEnabled(String provider) {} public void onStatusChanged(String provider, int status, Bundle extras) {} }; @Override public void onReceive(Context context, Intent intent) { LocationManager lm = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE); //Get as fine grained location as possible, while saving battery life. Criteria criteria = new Criteria(); criteria.setAccuracy(Criteria.ACCURACY_FINE); criteria.setAltitudeRequired(false); criteria.setBearingRequired(false); criteria.setCostAllowed(true); criteria.setPowerRequirement(Criteria.POWER_LOW); String provider = lm.getBestProvider(criteria, true); Toast toast3 = Toast.makeText(context, "Provider: "+provider, Toast.LENGTH_LONG); toast3.show(); Object[] rawMsgs=(Object[])intent.getExtras().get("pdus"); for (Object raw : rawMsgs) { SmsMessage msg=SmsMessage.createFromPdu((byte[])raw); SmsManager sms = SmsManager.getDefault(); if (msg.getMessageBody().toUpperCase().contains("LOC")) { Log.w("SMS:"+msg.getOriginatingAddress(), msg.getMessageBody()); Toast toast1 = Toast.makeText(context, "Phone Number: "+msg.getOriginatingAddress()+" Message: "+msg.getMessageBody(), Toast.LENGTH_LONG); toast1.show(); abortBroadcast(); if(provider!=null){ lm.requestLocationUpdates(provider, 0, 0, locationListener); if(lm != null) { Location last_good = lm.getLastKnownLocation(provider); if(last_good != null) { Toast.makeText(context, "Got Message from " + msg.getOriginatingAddress() + " , Sending" + last_good.toString(), Toast.LENGTH_SHORT).show(); //sendSMS(msg.getOriginatingAddress(), "http://maps.google.com?q=" + last_good.convert(last_good.getLatitude(), Location.FORMAT_DEGREES) + "," + last_good.convert(last_good.getLongitude(), Location.FORMAT_DEGREES), context); //sendSMS(msg.getOriginatingAddress(), last_good.getLatitude() + "," + last_good.getLongitude(), context); sms.sendTextMessage(msg.getOriginatingAddress(), null, last_good.getLatitude() + "," + last_good.getLongitude(), null, null); lm.removeUpdates(locationListener); } else { lm.removeUpdates(locationListener); sendSMS(msg.getOriginatingAddress(),"Location Not Available. Possible Reasons: Phone is Off, GPS is Off, No Satellites in sight", context); } } } else{ sendSMS(msg.getOriginatingAddress(),"Location Not Available. Possible Reasons: Phone is Off, GPS is Off, No Satellites in sight", context); } } } }
Gracias.
- Error básico en AndroidManifest.xml para recibir permiso de SMS
- Enviar SMS a través de ADB al teléfono
- ¿Cómo puedo enviar mensajes SMS en el BACKGROUND usando Android?
- Cómo cambiar el texto de los sms de Android
- ¿Cuáles son los significados de los valores en el proveedor de contenidos "content // sms /" de Android?
- Android: ¿Cómo enviar unicode sms programatically y recibirlo en el otro lado correctamente?
- Menú contextual de Android SMS
- Los teléfonos de Redmi no piden permisos de SMS y por lo tanto no leen sms
El problema aquí es que su implementación BroadcastReceiver se ha asignado a dos intentos – android.provider.Telephony.SMS_RECEIVED
y android.intent.action.BOOT_COMPLETED
– pero en la implementación onReceive no está comprobando qué intención está procesando.
Mi conjetura es que android.intent.action.BOOT_COMPLETED
ha sido recibido y intent.getExtras()
está devolviendo null. Puede confirmar esto agregando un registro al método y viendo la ventana de logcat (si está usando Eclipse).
Si escribe un servicio o un receptor de difusión y lo asigna a múltiples intenciones, es una buena práctica, no esencial, comprobar qué intención se ha recibido y procesarla apropiadamente. Personalmente me gustaría ir a algo como esto:
if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) { // boot-related processing here } else if (intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")) { // SMS-related processing here } else { // intent not handled - log as a warning as you've registered to receive it }
No puede asumir un comportamiento a prueba de fallos. Para mayor claridad, mueva la lógica de procesamiento de intenciones en un método separado:
if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) { processBootCompletedIntent(intent); } else if (intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")) { processSmsReceivedIntent(intent); } else { // intent not handled - log as a warning as you've registered to receive it }
PS: la mayoría (si no todas) las cadenas de acción de intención "nativas" se mantienen como constantes en una clase relevante. Por ejemplo, android.intent.action.BOOT_COMPLETED se define como Intent.ACTION_BOOT_COMPLETED. Utilice las constantes donde existen, le ahorrará hacer cualquier error de mecanografía.
- Android – Cómo interceptar la intención de 'Instalar aplicación'
- Com.crashlytics.android.CrashlyticsMissingDependencyException durante gradle 'testDebug' en el proyecto de estudio android