Soluciona problemas de servicios en primer plano

En esta página, se analizan algunos motivos habituales por los que pueden fallar los servicios en primer plano y se te ayuda a identificar la causa del problema.

En este documento, se analizan los siguientes problemas:

Antes de solucionar el problema, realiza lo siguiente:

Verifica si hay cambios recientes en los servicios en primer plano

Si los servicios en primer plano se usan de forma inadecuada, pueden tener efectos negativos en el rendimiento del dispositivo y la duración de batería. Por este motivo, las versiones de la plataforma de Android suelen realizar cambios en el comportamiento de los servicios en primer plano para limitar estos efectos negativos.

Si tienes problemas con los servicios en primer plano, consulta la documentación sobre los cambios en los servicios en primer plano y verifica si hay cambios recientes que puedan explicar tus problemas. Es especialmente importante verificar si hay cambios en las siguientes circunstancias:

  • El código del servicio en primer plano que antes funcionaba ahora falla
  • Acabas de comenzar a realizar pruebas en una nueva versión de la plataforma o cambiaste el nivel de API al que se orienta tu app.

Además, si estás probando tu dispositivo en una versión preliminar para desarrolladores de la plataforma, asegúrate de consultar la versión más reciente de la documentación de la versión preliminar para desarrolladores.

Errores de aplicación no responde (ANR)

En ciertas circunstancias, se espera que una app cierre su servicio en primer plano. Si la app no detiene el servicio, el sistema lo detiene y activa un error de Aplicación no responde (ANR).

El servicio corto se ejecuta durante demasiado tiempo, lo que provoca un error de ANR

Los servicios en primer plano que usan el tipo servicio corto deben completarse con rapidez, en un plazo de alrededor de tres minutos. Cuando se agota el tiempo, el sistema llama al método Service.onTimeout(int,int) del servicio. El servicio tiene unos segundos para llamar a stopSelf(). Si el servicio no se detiene, el sistema activa un error de Aplicación no responde.

Diagnóstico:

Si el error de ANR se produjo porque un servicio en primer plano no se detuvo, el sistema arroja una excepción interna. Puedes verificar que este haya sido el problema consultando los informes de ANR. Si este es el problema, el informe incluirá el siguiente mensaje:

Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type FOREGROUND_SERVICE_TYPE_SHORT_SERVICE did not stop within its timeout:
[component name]"

Solución:

Asegúrate de que todos los servicios en primer plano con límite de tiempo finalicen su trabajo y llamen a stopForeground(int) dentro del límite de tiempo del sistema.

Haz que tus servicios en primer plano implementen Service.onTimeout(int,int). Asegúrate de que tu implementación de ese método llame a stopSelf() de inmediato.

Excepciones de servicios en primer plano

En esta sección, se describen varios problemas de servicios en primer plano que pueden hacer que el sistema arroje una excepción. Si la app no detecta la excepción, el usuario verá un diálogo que le indicará que la app se detuvo.

En algunos casos, el sistema arroja una excepción interna. En esos casos, puedes averiguar cuál fue la excepción buscando en el seguimiento de pila y puedes consultar Logcat para obtener información más detallada sobre el error.

Excepción interna: Se agotó el tiempo de espera

El sistema impone un límite en el tiempo que pueden ejecutarse los servicios en primer plano de sincronización de datos y procesamiento de contenido multimedia mientras la app está en segundo plano. Si el servicio supera ese límite, el sistema llama al método Service.onTimeout(int,int) del servicio. El servicio tiene unos segundos para llamar a stopSelf(). Si el servicio no se detiene, el sistema genera una RemoteServiceException interna que hace que la app falle.

Diagnóstico:

Para averiguar cuál fue la excepción, consulta el seguimiento de pila y revisa Logcat para obtener información más detallada sobre el error. En este caso, Logcat tiene el siguiente mensaje de error:

Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type [service type] did not stop within its timeout: [component name]"

Solución:

Asegúrate de que todos los servicios en primer plano con límite de tiempo finalicen su trabajo y llamen a stopForeground(int) dentro del límite de tiempo del sistema.

Haz que tus servicios en primer plano implementen Service.onTimeout(int,int). Asegúrate de que tu implementación de ese método llame a stopSelf() de inmediato.

Excepción interna: ForegroundServiceDidNotStartInTimeException

Cuando inicias un servicio llamando a context.startForegroundService(), ese servicio tiene unos segundos para convertirse en un servicio en primer plano llamando a ServiceCompat.startForeground(). Si el servicio no lo hace, se arroja un error interno ForegroundServiceDidNotStartInTimeException.

Diagnóstico:

Para averiguar cuál fue la excepción, consulta el seguimiento de pila y revisa Logcat para obtener información más detallada sobre el error. En este caso, Logcat tiene el siguiente mensaje de error:

android.app.RemoteServiceException$ForegroundServiceDidNotStartInTimeException:
Context.startForegroundService() did not then call Service.startForeground()

Solución:

Asegúrate de que todos los servicios en primer plano recién creados llamen a ServiceCompat.startForeground() en unos segundos.

WorkManager:

También puedes ver esta excepción con trabajadores de WorkManager que ejecutan un servicio en primer plano (llaman a setForegound o setForegroundAsync). Cuando el ciclo de vida de dos trabajadores en primer plano se superpone, ya que un trabajador intenta iniciar un servicio en primer plano mientras un servicio en primer plano que se ejecutaba anteriormente intenta cerrarse, esta falla se acompañará del siguiente registro:

Re-initializing SystemForegroundService after a request to shut-down

Se introdujo una corrección para esta falla en la versión 2.10.5 de WorkManager.

Si tu app encuentra esta excepción, actualízala a la versión más reciente de WorkManager y, luego, informa cualquier problema persistente en la herramienta de seguimiento de errores de WorkManager.

ForegroundServiceStartNotAllowedException

Error:

El sistema arroja ForegroundServiceStartNotAllowedException.

Causa:

Por lo general, esto se debe a que la app inicia un servicio en primer plano desde el segundo plano cuando no hay una exención válida.

A partir de Android 12 (nivel de API 31), las apps no pueden iniciar servicios en primer plano mientras se ejecutan en segundo plano, con algunas excepciones específicas. Si intentas iniciar un servicio en primer plano desde el segundo plano y no cumples con los requisitos de una de las exenciones, el sistema arroja ForegroundServiceStartNotAllowedException. El sistema también hace esto si no cumples con los requisitos de la exención.

Por ejemplo, una app puede tener un botón en el que el usuario puede hacer clic, lo que hace que la app realice algún procesamiento y, luego, inicie un servicio en primer plano. En este caso, existe el peligro de que el usuario haga clic en el botón y, luego, ponga la app en segundo plano de inmediato. Luego, la app intentaría iniciar el servicio desde el segundo plano. Si la app no cumple con una de las excepciones especificadas, el sistema arroja una ForegroundServiceStartNotAllowedException.

Además, algunas exenciones tienen un límite de tiempo breve. Por ejemplo, existe una breve exención si tu app inicia un servicio en primer plano en respuesta a un mensaje de FCM de alta prioridad. Si no inicias el servicio con la rapidez suficiente, obtendrás un ForegroundServiceStartNotAllowedException.

A veces, las exenciones específicas se vuelven más restrictivas con las nuevas versiones de Android. Si cambiaste la versión de Android a la que se orienta tu app, consulta la documentación sobre los cambios en los servicios en primer plano y confirma que tu app aún cumpla con una de las excepciones permitidas.

Solución:

Cambia el flujo de trabajo de tu app para que no necesite iniciar servicios en primer plano mientras la app está en segundo plano o confirma que tu app cumple con una de las excepciones.

Puedes usar componentes optimizados para ciclos de vida para administrar el ciclo de vida de tu app, de modo que no intentes iniciar un servicio en primer plano desde el segundo plano de forma involuntaria.

SecurityException

Error:

El sistema arroja SecurityException.

Causa:

Tu app intentó iniciar un servicio en primer plano sin tener los permisos necesarios.

  • Si una app se orienta a Android 9 (nivel de API 28) o versiones posteriores, debe tener el permiso FOREGROUND_SERVICE para iniciar un servicio en primer plano.
  • Si una app se orienta a Android 14 (nivel de API 34) o una versión posterior, debe cumplir con todos los requisitos previos para su tipo de servicio en primer plano. Estos requisitos previos se detallan en la documentación de los tipos de servicios en primer plano. En particular, ten en cuenta los siguientes requisitos:
    • Varios tipos de servicios en primer plano requieren permisos de tiempo de ejecución específicos. Por ejemplo, un servicio en primer plano de mensajería remota debe tener el permiso FOREGROUND_SERVICE_REMOTE_MESSAGING.
  • En varios casos, existen restricciones adicionales de uso en los permisos que necesitan algunos tipos de servicios en primer plano. Estos permisos solo se otorgan a la app mientras está en primer plano (con algunas excepciones específicas). Esto significa que, incluso si tu app solicitó y obtuvo uno de estos permisos, si intenta iniciar el servicio en primer plano mientras está en segundo plano, el sistema arrojará una SecurityException, incluso si la app tiene una exención para iniciar un servicio en primer plano desde el segundo plano. Para obtener más información, consulta Restricciones para iniciar servicios en primer plano que necesitan permisos de uso.
    • Es posible que recibas un SecurityException si solicitaste los permisos necesarios, pero inicias el servicio en primer plano antes de confirmar que se otorgaron los permisos requeridos.

Solución:

Antes de iniciar el servicio en primer plano, solicita todos los permisos de servicio en primer plano adecuados y confirma que cumpliste con todos los demás requisitos previos del entorno de ejecución.