El propósito del servicio debe ser explícito: Intención
Ahora tengo una aplicación en la que llamo a un servicio a través de un receptor de difusión (MyStartupIntentReceiver). El código en el receptor de radiodifusión para llamar al servicio es:
public void onReceive(Context context, Intent intent) { Intent serviceIntent = new Intent(); serviceIntent.setAction("com.duk3r.eortologio2.MyService"); context.startService(serviceIntent); }
El problema es que en Android 5.0 Lollipop recibo el siguiente error (en versiones anteriores de Android, todo funciona bien):
- Cómo pasar un contexto de actividad en una aplicación a un servicio en otra aplicación
- El servicio de Android se detiene cuando se cierra la aplicación
- ¿Cómo usar loopJ SyncHttpClient para llamadas sincrónicas?
- Android.os.deadobjectexception en el servicio android
- Comunicarse desde la aplicación al servicio
Unable to start receiver com.duk3r.eortologio2.MyStartupIntentReceiver: java.lang.IllegalArgumentException: Service Intent must be explicit: Intent { act=com.duk3r.eortologio2.MyService }
¿Qué debo cambiar para que el servicio sea declarado explícito y comience normalmente? Probado algunas respuestas en otros temas similares, pero aunque me deshice del mensaje, el servicio no se inicia.
- Cómo obtener un Broadcastreceiver fiable
- ¿Cómo establecer una comunicación bidireccional entre Actividad y Servicio en diferentes procesos?
- ¿Cuándo debo usar unbindService (), y cómo debo usarlo correctamente para desvincularme de un servicio remoto que está utilizando una interfaz AIDL?
- Detener o matar un servicio
- ¿Por qué un servicio Android no es singleton cuando se prueba?
- Cómo autenticar servicio web sap con ksoap2
- Android - Iniciar un servicio con información adicional a través de put / getExtra
- Cómo mantener un servicio de Intent funcionando
Cualquier intención que realice en un servicio, actividad, etc. en su aplicación siempre debe seguir este formato
Intent serviceIntent = new Intent(context,MyService.class); context.startService(serviceIntent);
o
Intent bi = new Intent("com.android.vending.billing.InAppBillingService.BIND"); bi.setPackage("com.android.vending");
Las intenciones implícitas (lo que usted tiene en su código actualmente) se consideran un riesgo de seguridad
Establecer el nombre de packageName
funciona.
intent.setPackage(this.getPackageName());
Para la gente perezosa como yo sólo uso
public static Intent createExplicitFromImplicitIntent(Context context, Intent implicitIntent) { // Retrieve all services that can match the given intent PackageManager pm = context.getPackageManager(); List<ResolveInfo> resolveInfo = pm.queryIntentServices(implicitIntent, 0); // Make sure only one match was found if (resolveInfo == null || resolveInfo.size() != 1) { return null; } // Get component info and create ComponentName ResolveInfo serviceInfo = resolveInfo.get(0); String packageName = serviceInfo.serviceInfo.packageName; String className = serviceInfo.serviceInfo.name; ComponentName component = new ComponentName(packageName, className); // Create a new intent. Use the old one for extras and such reuse Intent explicitIntent = new Intent(implicitIntent); // Set the component to be explicit explicitIntent.setComponent(component); return explicitIntent;
}
Envíe el contexto y su intención en este método y obtenga la intención del resultado para usar.
Convierta la intención implícita en una intención explícita y luego en un servicio de inicio de incendios.
Intent implicitIntent = new Intent(); implicitIntent.setAction("com.duk3r.eortologio2.MyService"); Context context = getApplicationContext(); Intent explicitIntent = convertImplicitIntentToExplicitIntent(implicitIntent, context); if(explicitIntent != null){ context.startActivity(explicitIntent); } public static Intent convertImplicitIntentToExplicitIntent(Intent implicitIntent, Context context) { PackageManager pm = context.getPackageManager(); List<ResolveInfo> resolveInfoList = pm.queryIntentServices(implicitIntent, 0); if (resolveInfoList == null || resolveInfoList.size() != 1) { return null; } ResolveInfo serviceInfo = resolveInfoList.get(0); ComponentName component = new ComponentName(serviceInfo.serviceInfo.packageName, serviceInfo.serviceInfo.name); Intent explicitIntent = new Intent(implicitIntent); explicitIntent.setComponent(component); return explicitIntent; }
Prueba esto. esto funciona para mi. Aquí MonitoringService es mi clase de servicio. Tengo dos acciones, que indican el servicio para detener o iniciar. Envío ese valor de mi receptor de difusión depende de AIRPLANE_MODE_CHANGED .
@Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if(Intent.ACTION_AIRPLANE_MODE_CHANGED.equalsIgnoreCase(action)){ boolean isOn = intent.getBooleanExtra("state", false); String serviceAction = isOn? MonitoringService.StopAction : MonitoringService.StartAction; Intent serviceIntent = new Intent(context, MonitoringService.class); serviceIntent.setAction(serviceAction); context.startService(serviceIntent); } }
NOTA: agrego el siguiente código para activar mi receptor de difusión llamado: ManageLocationListenerReceiver .
<receiver android:name=".ManageLocationListenerReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.intent.action.AIRPLANE_MODE" /> </intent-filter> </receiver>