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 hubo 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 la 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, debes consultar la documentación sobre los cambios en los servicios en primer plano y verificar si hay cambios recientes que puedan explicar tus problemas. Es especialmente importante que verifiques si hay cambios en las siguientes circunstancias:

  • El código del servicio en primer plano que funcionaba anteriormente 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 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 short service 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 por sí solo, el sistema activa un error de aplicación que no responde.

Diagnóstico:

Si el error de ANR se debió a que un servicio en primer plano no pudo detenerse por sí solo, el sistema arroja una excepción interna. Para verificar que este fue el problema, revisa 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 consultar el registro de seguimiento de la pila para saber cuál fue la excepción y puedes consultar Logcat para obtener información más detallada sobre el error.

Excepción interna: Se superó 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 medios 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 por sí solo, el sistema genera un RemoteServiceException interno que provoca que la app falle.

Diagnóstico:

Para saber cuál fue la excepción, consulta el registro de seguimiento de la pila y, para obtener información más detallada sobre el error, revisa Logcat. 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 promocionarse como un servicio en primer plano llamando a ServiceCompat.startForeground(). Si el servicio no lo hace, arroja un ForegroundServiceDidNotStartInTimeException interno.

Diagnóstico:

Para saber cuál fue la excepción, consulta el registro de seguimiento de la pila y, para obtener información más detallada sobre el error, revisa Logcat. 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.

ForegroundServiceStartNotAllowedException

Error:

El sistema arroja ForegroundServiceStartNotAllowedException.

Causa:

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

A partir de Android 12 (nivel de API 31), no se permite que las apps inicien 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 podría tener un botón en el que un 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 en segundo plano. Si la app no cumple con una de las exenciones especificadas, el sistema arroja un ForegroundServiceStartNotAllowedException.

Además, algunas exenciones tienen un límite de tiempo corto. Por ejemplo, hay una breve excepció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 suficiente rapidez, obtendrás un elemento ForegroundServiceStartNotAllowedException.

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

Solución:

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

Puedes usar componentes que priorizan el ciclo de vida para administrar el ciclo de vida de tu app y evitar intentar iniciar un servicio en primer plano desde el segundo plano de forma involuntaria.

SecurityException

Error:

El sistema arrojaSecurityException.

Causa:

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

  • Si una app se segmenta para 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 segmenta para 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 servicio 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 de 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 se encuentra 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 durante el uso.
    • Es posible que obtengas un SecurityException si solicitaste los permisos necesarios, pero iniciaste 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 correspondientes y confirma que cumpliste con todos los demás requisitos previos del tiempo de ejecución.