support studio oreo jobserviceengineimpl jobintentservice example completed app android android-broadcastreceiver bootcompleted android-8.0-oreo

studio - Excepción de tiempo de ejecución Android O con boot_completed



broadcast receiver android studio (2)

Aquí hay algunas opciones que describí en una publicación de blog :

Solución # 1: startForegroundService ()

Su BroadcastReceiver que recibe la transmisión ACTION_BOOT_COMPLETED podría llamar a startForegroundService() lugar de startService() cuando esté en Android 8.0+:

import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.Build; public class OnBootReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Intent i=new Intent(context, TestIntentService.class); if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.O) { context.startForegroundService(i); } else { context.startService(i); } } }

Tenga en cuenta que esto funciona, hasta cierto punto, incluso si su servicio en realidad nunca llama startForeground() . Se le da una ventana de tiempo para llamar a startForeground() , "comparable al intervalo ANR para hacer esto". Si su trabajo es más largo que un milisegundo pero menos de unos pocos segundos, puede omitir la Notification y la llamada startForeground() . Sin embargo, obtendrá un error en LogCat:

E/AndroidRuntime: FATAL EXCEPTION: main Process: com.commonsware.myapplication, PID: 5991 android.app.RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground() at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1775) at android.os.Handler.dispatchMessage(Handler.java:105) at android.os.Looper.loop(Looper.java:164) at android.app.ActivityThread.main(ActivityThread.java:6541) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

Por supuesto, si no le importa tener una Notification brevemente, puede usar startForeground() como Android espera, en cuyo caso puede hacer un trabajo en segundo plano normalmente, aunque con una entrada que aparece en el tono de notificación del usuario.

Solución # 2: goAsync ()

BroadcastReceiver ofrece goAsync() desde el nivel 11 de API. Esto le permite a su receptor trabajar fuera del subproceso principal de la aplicación, por lo que podría deshacerse completamente de IntentService y mover su código al BroadcastReceiver . Aún tiene solo el período de tiempo de espera de ANR para trabajar, pero no estará atando el subproceso principal de la aplicación. Esto es mejor que la primera solución, en la medida en que tiene la misma limitación de tiempo pero evita el error desagradable. Sin embargo, requiere una cierta cantidad de reproceso.

Solución # 3: JobScheduler

Si su trabajo llevará más de unos pocos segundos y desea evitar la Notification , puede modificar su código para implementar un JobService trabajo y trabajar con JobScheduler . Esto tiene la ventaja adicional de que solo le da control cuando se cumplen otros criterios (por ejemplo, hay una conexión de Internet utilizable). Sin embargo, esto no solo requiere una reescritura, sino que JobScheduler solo está disponible en Android 5.0+, por lo que si su minSdkVersion es menor que 21, necesitará alguna otra solución en los dispositivos más antiguos.

ACTUALIZACIÓN : Eugen Pechanec señaló JobIntentService , que es un interesante mashup JobService / IntentService .

Estoy intentando iniciar un IntentService dentro de mi receptor BOOT_COMPLETED, pero en Android O (API 26) obtengo:

java.lang.RuntimeException: java.lang.IllegalStateException: Not allowed to start service Intent { act=intent.action.update cmp=packageName.services.OwnService }: app is in background

(El mensaje está en una línea, pero de esta manera es más fácil de leer)

¿Cómo puedo hacer esto de la manera correcta?