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?
Es posible que desee consultar la siguiente sección de la documentación de cambios en el comportamiento de Android O https://developer.android.com/preview/features/background.html#services
Ahora limita cuando la aplicación puede iniciar servicios en segundo plano.