Restricciones para iniciar un servicio en primer plano desde el segundo plano

Las apps orientadas a Android 12 (nivel de API 31) o versiones posteriores no pueden iniciar servicios en primer plano mientras se ejecutan en segundo plano, excepto en algunos casos especiales. Si una app intenta iniciar un servicio en primer plano mientras se ejecuta en segundo plano, y el servicio en primer plano no cumple con uno de los casos excepcionales, el sistema arroja una ForegroundServiceStartNotAllowedException.

Además, si una app quiere iniciar un servicio en primer plano que necesita permisos mientras está en uso (por ejemplo, permisos de sensores corporales, cámara, micrófono o ubicación), no puede crear el servicio mientras la app está en segundo plano, incluso si la app se encuentra en una de las excepciones de las restricciones de inicio en segundo plano. El motivo de esto se explica en la sección Restricciones para iniciar servicios en primer plano que necesitan permisos de uso.

Exenciones de las restricciones para el inicio en segundo plano

En las siguientes situaciones, la app puede iniciar servicios en primer plano, incluso cuando se ejecuta en segundo plano:

Restricciones para iniciar servicios en primer plano que necesitan permisos de uso

En Android 14 (nivel de API 34) o versiones posteriores, hay situaciones especiales que debes tener en cuenta si inicias un servicio en primer plano que necesita permisos de uso.

Si tu app se orienta a Android 14 o versiones posteriores, el sistema operativo verifica cuándo creas un servicio en primer plano para asegurarse de que tu app tenga todos los permisos adecuados para ese tipo de servicio. Por ejemplo, cuando creas un servicio en primer plano de tipo microphone, el sistema operativo verifica que tu app tenga el permiso RECORD_AUDIO. Si no tienes ese permiso, el sistema arroja una SecurityException.

En el caso de los permisos de uso, esto genera un problema potencial. Si tu app tiene un permiso de uso, solo tendrá ese permiso mientras esté en primer plano. Esto significa que, si tu app está en segundo plano y trata de crear un servicio en primer plano de tipo cámara, ubicación o micrófono, el sistema verá que tu app no tiene actualmente los permisos necesarios y arrojará una SecurityException.

Del mismo modo, si tu app está en segundo plano y crea un servicio de salud que necesita el permiso BODY_SENSORS, la app no tiene ese permiso en ese momento y el sistema arroja una excepción. (Esto no se aplica si se trata de un servicio de salud que necesita permisos diferentes, como ACTIVITY_RECOGNITION). Llamar a PermissionChecker.checkSelfPermission() no evita este problema. Si tu app tiene un permiso de uso, y llama a checkSelfPermission() para verificar si tiene ese permiso, el método devuelve PERMISSION_GRANTED, incluso si la app está en segundo plano. Cuando el método devuelve PERMISSION_GRANTED, significa que "tu app tiene este permiso mientras está en uso".

Por este motivo, si tu servicio en primer plano necesita un permiso de uso, debes llamar a Context.startForegroundService() o Context.bindService() mientras tu app tenga una actividad visible, a menos que el servicio se encuentre en una de las exenciones definidas.

Exenciones de las restricciones de los permisos de uso en primer plano

En algunas situaciones, incluso si se inicia un servicio en primer plano mientras la app se ejecuta en segundo plano, puede acceder a la información de ubicación, cámara y micrófono mientras la app se ejecuta en primer plano ("mientras está en uso").

En estas mismas situaciones, si el servicio declara un tipo de servicio en primer plano de location y lo inicia una app que tiene el permiso ACCESS_BACKGROUND_LOCATION, este servicio puede acceder a la información de ubicación todo el tiempo, incluso cuando la app se ejecuta en segundo plano.

En la siguiente lista, se incluyen estas situaciones:

  • Un componente del sistema inicia el servicio.
  • El servicio comienza interactuando con los widgets de la app.
  • El servicio se inicia interactuando con una notificación.
  • El servicio se inicia como un PendingIntent que se envía desde una app diferente y visible.
  • El servicio se inicia con una app que es un controlador de políticas de dispositivos que se ejecuta en el modo de propietario del dispositivo.
  • El servicio se inicia con una app que proporciona el VoiceInteractionService.
  • El servicio se inicia con una app que tiene el permiso con privilegios START_ACTIVITIES_FROM_BACKGROUND.

Cómo determinar qué servicios se ven afectados en tu app

Cuando pruebes tu app, inicia sus servicios en primer plano. Si un servicio iniciado tiene acceso restringido a la ubicación, el micrófono y la cámara, aparecerá el siguiente mensaje en Logcat:

Foreground service started from background can not have \
location/camera/microphone access: service SERVICE_NAME