Al iniciar la aplicación, la aplicación inicia el servicio que debería realizar alguna tarea de red. Después de apuntar al nivel 26 de API, mi aplicación no puede iniciar el servicio en Android 8.0 en segundo plano.
Causado por: java.lang.IllegalStateException: No se permite iniciar el servicio Intención {cmp = my.app.tt / com.my.service}: la aplicación está en segundo plano uidRecord {90372b1 u0a136 CEM inact procs: 1 seq (0,0 , 0)}
según tengo entendido relacionado con: Límites de ejecución en segundo plano
El método startService () ahora arroja una IllegalStateException si una aplicación dirigida a Android 8.0 intenta usar ese método en una situación en la que no está permitido crear servicios en segundo plano.
" en una situación en la que no está permitido ", ¿qué significa realmente? Y como arreglarlo. No quiero establecer mi servicio como "primer plano"
startForegroundService()
lugar destartService()
.Respuestas:
Las situaciones permitidas son una lista blanca temporal donde el servicio en segundo plano se comporta igual que antes de Android O.
Fuente: https://developer.android.com/about/versions/oreo/background.html
En otras palabras, si su servicio en segundo plano no cumple con los requisitos de la lista blanca, debe usar el nuevo JobScheduler . Básicamente es lo mismo que un servicio en segundo plano, pero se llama periódicamente en lugar de ejecutarse en segundo plano continuamente.
Si está utilizando un IntentService, puede cambiar a un JobIntentService. Vea la respuesta de @ kosev a continuación .
fuente
FirebaseInstanceIdService
y suonTokenRefresh
método un mensaje FCM de alta prioridad?Tengo solución Para dispositivos anteriores a 8.0, solo tiene que usar
startService()
, pero para dispositivos posteriores a 7.0, debe usarstartForgroundService()
. Aquí hay una muestra de código para iniciar el servicio.Y en la clase de servicio, agregue el siguiente código para la notificación:
Donde O es la versión 26 de Android.
fuente
ContextCompat.startForegroundService(...)
lib de soporte que se puede usar en su lugar.La mejor manera es usar JobIntentService que utiliza el nuevo JobScheduler para Oreo o los servicios antiguos si no están disponibles.
Declara en tu manifiesto:
Y en su servicio debe reemplazar onHandleIntent por onHandleWork:
Entonces comienzas tu servicio con:
fuente
enqueueWork(...)
es un método estático también.Si el servicio se ejecuta en un subproceso en segundo plano extendiéndolo
IntentService
, puede reemplazarloIntentService
con elJobIntentService
que se proporciona como parte de la Biblioteca de soporte de AndroidLa ventaja de usar
JobIntentService
es que se comporta como unIntentService
dispositivo pre-O y en O y superior, lo envía como un trabajoJobScheduler
también se puede usar para trabajos periódicos / bajo demanda. Pero, asegúrese de manejar la compatibilidad con versiones anteriores, ya queJobScheduler
API solo está disponible desde API 21fuente
En Oreo, Android define límites a los servicios en segundo plano .
Aún así, si necesita un servicio siempre en ejecución, puede utilizar el servicio en primer plano.
Para que pueda hacer un servicio en primer plano . Deberá mostrar una notificación al usuario cuando su servicio se esté ejecutando. Ver esta respuesta (Hay muchas otras)
Una solución si -
no quieres una notificación por tu servicio?
Puede usar tareas periódicas con Alarm Manager , Job Scheduler , Evernote-Jobs o Work Manager .
He probado el servicio en ejecución permanente con Work-Manager.
fuente
Sí, eso se debe a que ya no puede iniciar servicios en segundo plano en API 26. Por lo tanto, puede iniciar ForegroundService por encima de API 26.
Tendrás que usar
y publicar una notificación mientras procesa la fuga.
fuente
Como @kosev dijo en su respuesta , puede usar JobIntentService. Pero uso una solución alternativa: capto IllegalStateException e inicio el servicio como primer plano. Por ejemplo, esta función inicia mi servicio:
y cuando proceso Intent, hago tal cosa:
fuente
context.startService
funciona en segundo plano - a veces no - esto se ve como la única mejor manera de lo contrario se tienen que implementar más código en su clase principalextending Application
yimplementing ActivityLifecycleCallbacks
y realizar un seguimiento de si la aplicación está en el primer o segundo plano y comenzar su intención en consecuencia.Según las notas de la versión de Firebase , afirman que el soporte para Android O se lanzó por primera vez en 10.2.1 (aunque recomendaría usar la versión más reciente).
agregue nuevas dependencias de mensajería firebase para Android O
Actualice los servicios de Google Play y los repositorios de Google si es necesario.
fuente
Si alguna intención funcionaba bien antes cuando la aplicación está en segundo plano, ya no será el caso de Android 8 y superior. Solo se refiere a la intención que tiene que hacer algún procesamiento cuando la aplicación está en segundo plano.
Deben seguirse los siguientes pasos:
JobIntentService
lugar deIntentService
.La clase que se extiende
JobIntentService
debe implementar elonHandleWork(@NonNull Intent intent)
método - y debe tener debajo del método, que invocará elonHandleWork
método:Llame
enqueueWork(Context, intent)
desde la clase donde se define su intención.Código de muestra:
com.android.support:support-compat
es necesario paraJobIntentService
- yo uso26.1.0 V
.Lo más importante es asegurarse de que la versión de las bibliotecas de Firebase esté activa, al menos
10.2.1
, tuve problemas con10.2.0
- si es que tienes algunoSu manifiesto debe tener el siguiente permiso para la clase de Servicio:
Espero que esto ayude.
fuente
Veo muchas respuestas que recomiendan simplemente usar un ForegroundService. Para usar un Servicio Foreground, debe haber una notificación asociada a él. Los usuarios verán esta notificación. Dependiendo de la situación, pueden molestarse con su aplicación y desinstalarla.
La solución más fácil es usar el nuevo Componente de Arquitectura llamado WorkManager. Puede consultar la documentación aquí: https://developer.android.com/topic/libraries/architecture/workmanager/
Simplemente define su clase de trabajador que extiende a Trabajador.
Luego, programa cuándo quieres ejecutarlo.
¡Fácil! Hay muchas formas de configurar trabajadores. Admite trabajos recurrentes e incluso puede hacer cosas complejas como encadenar si lo necesita. Espero que esto ayude.
fuente
WorkManager is intended for tasks that are deferrable—that is, not required to run immediately
... podría ser más fácil, sin embargo, mi aplicación necesita un servicio en segundo plano que ejecute las solicitudes de los usuarios de inmediato.Solución alternativa mediante JobScheduler, puede iniciar el servicio en segundo plano en intervalos regulares de tiempo.
En primer lugar, crea la clase llamada Util.java
Luego, haga la clase JobService llamada TestJobService.java
Después de esa clase de receptor BroadCast llamada ServiceReceiver.java
Actualizar archivo de manifiesto con servicio y código de clase del receptor
Izquierda main_intent launcher al archivo mainActivity.java que se crea por defecto, y los cambios en el archivo MainActivity.java son
WOOAAH !! El servicio en segundo plano comienza sin el servicio en primer plano
fuente
Si está ejecutando su código en 8.0, la aplicación se bloqueará. Entonces comience el servicio en primer plano. Si debajo de 8.0 usa esto:
Si es anterior o 8.0, use esto:
fuente
java.lang.SecurityException: Permission Denial: startForeground from pid=13708, uid=10087 requires android.permission.FOREGROUND_SERVICE
. Corrección en stackoverflow.com/a/52382711/550471si ha integrado la notificación push de mensajería firebase entonces,
Agregue nuevas dependencias de mensajería firebase para Android O (Android 8.0), debido a los Límites de ejecución en segundo plano .
Actualice los servicios de Google Play y los repositorios de Google si es necesario.
Actualizar:
fuente
Use en
startForegroundService()
lugar destartService()
y no olvide crearstartForeground(1,new Notification());
en su servicio dentro de los 5 segundos posteriores al inicio del servicio.fuente
Debido a los controvertidos votos sobre esta respuesta (+ 4 / -4 a partir de esta edición), MIRE PRIMERO LAS OTRAS RESPUESTAS Y UTILICE ESTO SOLO COMO ÚLTIMO RECURSO . Solo usé esto una vez para una aplicación de red que se ejecuta como root y estoy de acuerdo con la opinión general de que esta solución no debe usarse en circunstancias normales.
Respuesta original a continuación:
Las otras respuestas son correctas, pero me gustaría señalar que otra forma de evitar esto es pedirle al usuario que desactive las optimizaciones de batería para su aplicación (esto generalmente no es una buena idea a menos que su aplicación esté relacionada con el sistema). Consulte esta respuesta para saber cómo solicitar la exclusión de las optimizaciones de batería sin que su aplicación sea bloqueada en Google Play.
También debe verificar si las optimizaciones de la batería están desactivadas en su receptor para evitar fallas a través de:
fuente
JobScheduler
y otras cosas. Algunas de las aplicaciones necesitan funcionar a un nivel más bajo que las aplicaciones de sincronización típicas. Esta es una solución alternativa cuando eso no funciona.no use en onStartCommand:
solo cámbielo a:
y va a funcionar
fuente