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 te ayuda a identificar el 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 a menudo realizan cambios en el comportamiento del servicio en primer plano para limitar estos efectos negativos.

Si tienes problemas con los servicios en primer plano, debes consultar la documentación sobre los cambios en los servicios en primer plano y ver si hay algún cambio reciente que pueda explicar tus problemas. Es especialmente importante verificar si hay cambios en las siguientes circunstancias:

  • El código del servicio en primer plano que funcionaba antes 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 determinadas 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 que no responde (ANR).

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

Los servicios en primer plano que usan el tipo de servicio corto deben completarse rápidamente, en aproximadamente 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 que no responde.

Diagnóstico:

Si el error de ANR se debe a que un servicio en primer plano no se detuvo, el sistema arroja una excepción interna. Para verificar que este fue el problema, consulta Logcat. En este caso, el registro incluye 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 tiempo limitado terminen 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 la 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 ve un diálogo que le indica que la app se detuvo.

En algunos casos, el sistema arroja una excepción interna. No puedes detectar esas excepciones, pero puedes buscar en Logcat para ver qué excepción se generó.

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

El sistema impone un límite sobre 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 excepción interna que hace que la app falle.

Diagnóstico:

Si el tiempo de espera se agotó, Logcat incluye el siguiente mensaje:

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 tiempo limitado terminen 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 la implementación de ese método llame a stopSelf() de inmediato.

Excepción interna: ForegroundServiceDidNotStartInTimeException

Cuando llamas a context.startForegroundService() para iniciar un servicio, ese servicio tiene unos segundos para promocionarse a un servicio en primer plano llamando a ServiceCompat.startForeground(). Si el servicio no lo hace, el sistema activa un error de ANR.

Diagnóstico:

Si un servicio en primer plano no se inició a tiempo, la app fallará, lo que hará que el usuario vea un diálogo Se detuvo la app. En este caso, puedes encontrar el siguiente mensaje en Logcat:

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

Solución:

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

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 lo hace 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 un 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. En este caso, la app intentaría iniciar el servicio desde segundo plano. Si la app no cumple con una de las exenciones especificadas, el sistema arroja una ForegroundServiceStartNotAllowedException.

Además, algunas exenciones tienen un límite de tiempo corto. Por ejemplo, hay 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 lo suficientemente rápido, 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 siga cumpliendo con una de las exenciones permitidas.

Solución:

Cambia el flujo de trabajo de tu app para que no tenga que iniciar servicios en primer plano mientras está en segundo plano, o bien confirma que cumpla con una de las exenciones.

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

SecurityException

Error:

El sistema arrojaSecurityException.

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 está orientada a Android 14 (nivel de API 34) o versiones posteriores, 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 durante el uso en los permisos que necesitan algunos tipos de servicios en primer plano. Estos permisos solo se otorgan a la app mientras esta está en primer plano (con algunas excepciones específicas). Esto significa que, incluso si tu app solicitó uno de estos permisos y se le otorgó, si intenta iniciar el servicio en primer plano mientras se ejecuta en segundo plano, el sistema arrojará una SecurityException, incluso si la app tiene una exención para iniciar un servicio en primer plano desde segundo plano. Para obtener más información, consulta Restricciones para iniciar servicios en primer plano que necesitan permisos durante el uso.
    • Es posible que obtengas 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 cumples con todos los demás requisitos previos del entorno de ejecución.