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):
- Temporizador Se ralentiza en Servicio cuando se bloquea la pantalla del dispositivo
- Priorizar la programación del reinicio del servicio androide bloqueado
- Tarea del temporizador VS Uso del administrador de alarmas en el servicio de Android
- Vincular servicio a la actividad en Android
- Android: Pasar variables a un servicio ya en ejecución
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.
- Servicio Android android.os.BinderProxy error
- ¿Cómo crear un proveedor de contenido en perfiles de usuario?
- Detener o matar un servicio
- Cómo evitar que el servicio se ejecute de nuevo si ya está ejecutando android
- ¿Cómo utilizo Android SpeechRecognizer como servicio?
- Servicio de primer plano que se está matando en el clic de notificación
- ¿Cómo obtengo el nombre de una clase de servicio en Android?
- ¿Por qué no comienza este servicio simple?
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>