Los servicios en primer plano realizan operaciones visibles para el usuario.
Los servicios en primer plano muestran una barra de estado , para que los usuarios sepan que tu La app realiza una tarea en primer plano y consume recursos del sistema.
Entre los ejemplos de apps que usan servicios en primer plano, se incluyen los siguientes:
- Una app que reproduce música en un servicio en primer plano La notificación podría mostrar la canción actual que se está reproduciendo.
- Una app de fitness que registra cuando un usuario corre en un servicio en primer plano, después de obtener el permiso del usuario. Es posible que la notificación muestre la distancia que el usuario recorrió durante la sesión de entrenamiento actual.
Usa servicios en primer plano solo cuando tu app necesite realizar una tarea que el usuario puede notar, aunque no esté interactuando directamente la aplicación. Si la acción es de poca importancia como para usar una notificación de prioridad mínima, crea una cuenta de segundo plano tarea en su lugar.
En este documento, se describe el permiso necesario para usar los servicios en primer plano, y cómo iniciar un servicio en primer plano y quitarlo del segundo plano. También se describe cómo asociar ciertos casos de uso con tipos de servicios en primer plano las restricciones de acceso que se aplican cuando se inicia un servicio en primer plano desde una app que se ejecuta en segundo plano.
El usuario puede descartar la notificación de forma predeterminada
A partir de Android 13 (nivel de API 33), los usuarios pueden descartar la notificación se asocia con un servicio en primer plano de forma predeterminada. Para ello, los usuarios deben deslizar el dedo en la notificación. Tradicionalmente, la notificación No se descarta, a menos que se detenga o quite el servicio en primer plano. en primer plano.
Si quieres que el usuario no pueda descartar la notificación, pasa
true
al setOngoing()
cuando crees la notificación con Notification.Builder
.
Servicios que muestran una notificación de inmediato
Si un servicio en primer plano tiene al menos una de las siguientes características, el muestra la notificación asociada inmediatamente después de que se inicia el servicio incluso en dispositivos que ejecutan Android 12 o versiones posteriores:
- El servicio está asociado con una notificación que incluye botones de acción.
- El servicio tiene un
foregroundServiceType
demediaPlayback
,mediaProjection
ophoneCall
. - El servicio proporciona un caso de uso relacionado con las llamadas telefónicas, la navegación o la reproducción multimedia, como se define en el atributo de categoría de la notificación.
- Para inhabilitar el cambio de comportamiento, el servicio pasó
FOREGROUND_SERVICE_IMMEDIATE
asetForegroundServiceBehavior()
cuando configuró la notificación.
En Android 13 (nivel de API 33) o versiones posteriores, si el usuario rechaza la permiso de notificaciones, siguen viendo avisos relacionados con los servicios en primer plano en la Administrador de tareas pero no las ves en el panel lateral de notificaciones.
Cómo declarar servicios en primer plano en tu manifiesto
En el manifiesto de la app, declara cada uno de sus servicios en primer plano
con un <service>
. Para cada servicio, usa un
Atributo android:foregroundServiceType
para declarar qué tipo de trabajo realiza.
Por ejemplo, si tu app crea un servicio en primer plano que reproduce música, podría declarar el servicio de la siguiente manera:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" ...>
<application ...>
<service
android:name=".MyMediaPlaybackService"
android:foregroundServiceType="mediaPlayback"
android:exported="false">
</service>
</application>
</manifest>
Si tus varios tipos se aplican a tu servicio, sepáralos con |
.
como "autor" y "título"
usando un operador lógico. Por ejemplo, un servicio que usa la cámara y el micrófono
la declararía así:
android:foregroundServiceType="camera|microphone"
Cómo solicitar los permisos del servicio en primer plano
Apps orientadas a Android 9 (nivel de API 28) o versiones posteriores y que usan servicios en primer plano
deberás solicitar
FOREGROUND_SERVICE
en el manifiesto de la app, como se muestra en el siguiente fragmento de código. Esta es una situación normal
permiso, por lo que el sistema
se lo otorga automáticamente a la app solicitante.
Además, si la app tiene como objetivo el nivel de API 34 o uno superior, debe solicitar el nivel de acceso
el tipo de permiso adecuado para la clase de trabajo que realizará el servicio en primer plano
están haciendo. Cada tipo de servicio en primer plano
tiene un tipo de permiso correspondiente. Por ejemplo, si una app inicia un
servicio en primer plano que use la cámara, debes solicitar el
FOREGROUND_SERVICE
y FOREGROUND_SERVICE_CAMERA
permisos. Todos estos son permisos normales, por lo que el sistema los otorga
automáticamente si están incluidos en el manifiesto.
<manifest xmlns:android="http://schemas.android.com/apk/res/android" ...>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CAMERA"/>
<application ...>
...
</application>
</manifest>
Requisitos previos del servicio en primer plano
A partir de Android 14 (nivel de API 34), cuando inicias un servicio en primer plano,
el sistema verifica requisitos previos específicos
según el tipo de servicio. Por ejemplo:
Si intentas iniciar un servicio en primer plano de tipo location
, el sistema verificará
para asegurarte de que tu app ya tenga ACCESS_COARSE_LOCATION
o
el permiso ACCESS_FINE_LOCATION
. Si no lo hace, el sistema genera
SecurityException
Por este motivo, debes confirmar que se cumplan los requisitos previos antes de iniciar un servicio en primer plano. El servicio en primer plano tipo de documentación se enumeran los requisitos previos necesarios para cada tipo de servicio en primer plano.
Cómo iniciar un servicio en primer plano
Antes de solicitar al sistema que ejecute un servicio como servicio en primer plano, inicia el servicio en sí:
Kotlin
val intent = Intent(...) // Build the intent for the service context.startForegroundService(intent)
Java
Context context = getApplicationContext(); Intent intent = new Intent(...); // Build the intent for the service context.startForegroundService(intent);
Dentro del servicio, por lo general en onStartCommand()
, puedes solicitar
que tu servicio se ejecute en primer plano. Para hacerlo, llama a
ServiceCompat.startForeground()
(disponible en androidx-core 1.12 y versiones posteriores). Este método toma lo siguiente
parámetros:
- El servicio
- Un número entero positivo que identifica de forma exclusiva la notificación en la barra de estado
- El objeto
Notification
en sí - Los tipos de servicio en primer plano identificar el trabajo que realiza el servicio
Estos tipos pueden ser un subconjunto de los tipos declarados en el manifiesto.
según el caso de uso específico. Luego, si necesitas agregar más tipos de servicios
puedes volver a llamar a startForeground()
.
Por ejemplo, imagina que una aplicación
de fitness ejecuta un servicio de seguimiento de carreras
necesita información de location
, pero es posible que deba reproducir contenido multimedia o no. Tú
tendría que declarar location
y mediaPlayback
en el manifiesto. Si un
usuario inicia una carrera y solo quiere que se haga un seguimiento de su ubicación, tu app debe llamar
startForeground()
y pasa solo el permiso ACCESS_FINE_LOCATION
. Luego,
Si el usuario quiere comenzar a reproducir audio, vuelve a llamar a startForeground()
y
pasar la combinación a nivel de bits de todos los tipos de servicios en primer plano (en este caso,
ACCESS_FINE_LOCATION|FOREGROUND_SERVICE_MEDIA_PLAYBACK
).
El siguiente es un ejemplo que inicia un servicio de cámara en primer plano:
Kotlin
class MyCameraService: Service() { private fun startForeground() { // Before starting the service as foreground check that the app has the // appropriate runtime permissions. In this case, verify that the user has // granted the CAMERA permission. val cameraPermission = PermissionChecker.checkSelfPermission(this, Manifest.permission.CAMERA) if (cameraPermission != PermissionChecker.PERMISSION_GRANTED) { // Without camera permissions the service cannot run in the foreground // Consider informing user or updating your app UI if visible. stopSelf() return } try { val notification = NotificationCompat.Builder(this, "CHANNEL_ID") // Create the notification to display while the service is running .build() ServiceCompat.startForeground( /* service = */ this, /* id = */ 100, // Cannot be 0 /* notification = */ notification, /* foregroundServiceType = */ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA } else { 0 }, ) } catch (e: Exception) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && e is ForegroundServiceStartNotAllowedException) { // App not in a valid state to start foreground service // (e.g. started from bg) } // ... } } }
Java
public class MyCameraService extends Service { private void startForeground() { // Before starting the service as foreground check that the app has the // appropriate runtime permissions. In this case, verify that the user // has granted the CAMERA permission. int cameraPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA); if (cameraPermission == PackageManager.PERMISSION_DENIED) { // Without camera permissions the service cannot run in the // foreground. Consider informing user or updating your app UI if // visible. stopSelf(); return; } try { Notification notification = new NotificationCompat.Builder(this, "CHANNEL_ID") // Create the notification to display while the service // is running .build(); int type = 0; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { type = ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA; } ServiceCompat.startForeground( /* service = */ this, /* id = */ 100, // Cannot be 0 /* notification = */ notification, /* foregroundServiceType = */ type ); } catch (Exception e) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && e instanceof ForegroundServiceStartNotAllowedException ) { // App not in a valid state to start foreground service // (e.g started from bg) } // ... } } //... }
Quita un servicio del primer plano
Para quitar el servicio del primer plano, llama
stopForeground()
Este método tiene un valor booleano, que indica si se debe quitar la barra de estado.
notificación. Ten en cuenta que el servicio sigue ejecutándose.
Si detienes el servicio mientras se ejecuta en primer plano, su notificación se quita.
Cómo controlar la detención iniciada por el usuario de las apps que ejecutan servicios en primer plano
A partir de Android 13 (nivel de API 33), los usuarios pueden completar un flujo de trabajo desde la panel lateral de notificaciones para detener una app que tiene servicios en primer plano en curso, independientemente de la configuración versión de destino del SDK. Esta indicación visual, denominada El Administrador de tareas muestra una lista de las apps que están que actualmente ejecuta un servicio en primer plano.
Esta lista tiene la etiqueta Apps activas. Junto a cada app, hay un botón Detener. En la Figura 1, se ilustra Flujo de trabajo del Administrador de tareas en un dispositivo que se ejecuta Android 13
Cuando el usuario presiona el botón Detener junto a tu app en la Administrador de tareas, ocurrirá lo siguiente:
- El sistema quita tu app de la memoria. Por lo tanto, toda tu app se detiene, no solo el servicio en primer plano en ejecución.
- El sistema quita la pila de actividades de actividad de tu app.
- Se detendrá cualquier reproducción de contenido multimedia.
- Se quita la notificación asociada con el servicio en primer plano.
- Tu app permanecerá en el historial.
- Los trabajos programados se ejecutan a la hora programada.
- Las alarmas suenan en la hora programada o en la ventana horaria.
Para probar que tu app se comporte como se espera mientras un usuario detiene tu ejecuta el siguiente comando de ADB en una ventana de terminal:
adb shell cmd activity stop-app PACKAGE_NAME
Exenciones
El sistema brinda varios niveles de exenciones para ciertos tipos de apps, que se describen en las siguientes secciones.
Las exenciones se aplican por app y no por proceso. Si el sistema exime un proceso en una app, todos los demás procesos de esa app también quedan eximidos.
Exenciones para aparecer en el Administrador de tareas
Las siguientes apps pueden ejecutar un servicio en primer plano y no aparecer en la Administrador de tareas:
- Apps a nivel del sistema
- Apps de seguridad (es decir, aquellas que tienen el rol
ROLE_EMERGENCY
) - Dispositivos que están en el modo de demostración
Exenciones con respecto a la finalización por parte de los usuarios
Cuando los siguientes tipos de aplicaciones ejecutan un servicio en primer plano, aparecen en la Administrador de tareas, pero no hay ningún botón Detener junto a la nombre de la aplicación para que el usuario presione:
- Apps del propietario del dispositivo
- Apps del propietario del perfil
- Apps persistentes
- Apps que tienen el rol
ROLE_DIALER
Usa APIs específicas en lugar de servicios en primer plano
En muchos casos de uso, hay APIs de plataforma o Jetpack que puedes usar para trabajar para los que, de lo contrario, usarías un servicio en primer plano. Si existe un acuerdo una API con propósitos específicos, deberías usarla casi siempre en lugar de usar un objeto servicio. Las APIs con propósitos específicos suelen proporcionar acceso adicional específico para casos de uso que, de lo contrario, tendrías que desarrollar por tu cuenta. Por ejemplo: la API de Bubbles controla la compleja lógica de la IU para apps de mensajería que necesiten implementar funciones de burbujas de chat.
En la documentación de los tipos de servicio en primer plano se enumeran buenas alternativas para usarlos en lugar de los servicios en primer plano.
Restricciones sobre el inicio de un servicio en primer plano desde el segundo plano
Las apps orientadas a Android 12 o versiones posteriores no pueden iniciar el primer plano
servicios mientras la aplicación se ejecuta en segundo plano, excepto por algunas especiales
casos. Si una app intenta iniciar una
servicio en primer plano mientras la app se ejecuta en segundo plano y en primer plano
no satisface uno de los casos excepcionales, el sistema arroja un
ForegroundServiceStartNotAllowedException
Además, si una app quiere iniciar un servicio en primer plano que necesite durante el uso (por ejemplo, sensor corporal, cámara, micrófono o ubicación permisos), no puede crear el servicio mientras la aplicación está en segundo plano, incluso si la app se encuentra en una de las exenciones del inicio en segundo plano de manera predeterminada. Este es el motivo que se explica en la sección Restricciones para iniciar servicios en primer plano que necesitan durante el uso permisos.
Exenciones de las restricciones para el inicio en segundo plano
En las siguientes situaciones, tu app puede iniciar servicios en primer plano incluso mientras tu app se ejecuta en segundo plano:
- La app viene de un estado visible para el usuario, como una actividad.
- La app puede iniciar una actividad en segundo plano, excepto en los casos en que tiene una actividad en la pila de actividades de una tarea existente.
Tu app recibe un mensaje de alta prioridad con Firebase Cloud. Mensajes.
El usuario realiza una acción en un elemento de la IU relacionado con tu app. Por ejemplo, puede interactuar con un cuadro de ayuda, una notificación, un widget o una actividad.
Tu app invoca una alarma exacta para completar una acción que el usuario solicita.
Tu app es la entrada actual del dispositivo. método.
Tu app recibe un evento relacionado con el geovallado o la transición del reconocimiento de actividad.
Después de que el dispositivo se reinicia y recibe la acción de intent
ACTION_BOOT_COMPLETED
,ACTION_LOCKED_BOOT_COMPLETED
oACTION_MY_PACKAGE_REPLACED
en un receptor de emisión.La app recibe la acción de intent
ACTION_TIMEZONE_CHANGED
,ACTION_TIME_CHANGED
oACTION_LOCALE_CHANGED
en un receptor de emisión.Tu app recibe el
ACTION_TRANSACTION_DETECTED
evento deNfcService
.Apps que tienen permisos o funciones del sistema específicos, como propietarios del dispositivo y propietarios de perfiles.
Tu app usa el Administrador de dispositivo complementario y declara la
REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND
permiso o elREQUEST_COMPANION_RUN_IN_BACKGROUND
permiso. Siempre que sea posible, utilizaREQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND
Tu app contiene las
SYSTEM_ALERT_WINDOW
permiso.Si el usuario desactiva las optimizaciones de la batería de tu app.
Restricciones sobre el inicio de servicios en primer plano que necesitan permisos durante el uso
En Android 14 (nivel de API 34) o versiones posteriores, hay situaciones especiales que se deben tener en cuenta si inicias un servicio en primer plano que necesita permisos de uso.
Si tu app está orientada a Android 14 o versiones posteriores, el sistema operativo
cuando creas un servicio en primer plano para asegurarte de que tu app tenga
los permisos adecuados para ese tipo de servicio. Por ejemplo, cuando creas un
servicio en primer plano de tipo
microphone, el operador
del sistema verifica que tu app actualmente tenga
RECORD_AUDIO
permiso. Si no tienes ese permiso, el sistema arrojará una
SecurityException
En el caso de los permisos durante el uso, esto genera un posible problema. Si tu app tiene un
permiso durante el uso, solo lo cuenta mientras esté en
primer plano. Esto significa que si tu app está en segundo plano e intenta crear
un servicio en primer plano de tipo cámara, ubicación o micrófono, el sistema ve
que tu app no actualmente no tiene los permisos necesarios y arroja un mensaje
SecurityException
Del mismo modo, si tu app está en segundo plano y crea una
servicio de salud que necesita el permiso BODY_SENSORS_BACKGROUND
, la app
actualmente no tiene ese permiso, 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
PermissionChecker.checkSelfPermission()
no evita este problema. Si tu app tiene un permiso durante el uso
este 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 muestra PERMISSION_GRANTED
, indica "tu app tiene este permiso
mientras la app está en uso".
Por este motivo, si tu servicio en primer plano necesita un permiso durante el uso, puedes
debe llamar a Context.startForegroundService()
o Context.bindService()
mientras
tu aplicación tiene una actividad visible, a menos que el servicio pertenezca a una de las
exenciones definidas.
Exenciones a las restricciones de permisos durante el uso
En algunas situaciones, incluso si se inicia un servicio en primer plano mientras la app ejecuciones en segundo plano, todavía puede acceder a la ubicación información de la cámara y el micrófono mientras la app se ejecuta en primer plano ("durante el 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
ACCESS_BACKGROUND_LOCATION
permiso, este servicio puede acceder a la información de la ubicación todo el tiempo, aun cuando
la aplicación se ejecuta en segundo plano.
La siguiente lista incluye estas situaciones:
- Un componente del sistema inicia el servicio.
- El servicio comienza interactuando con la app widgets.
- El servicio comienza interactuando con una notificación.
- El servicio comienza
PendingIntent
que se envía desde un una app diferente y visible. - El servicio se inicia con una app que es una política de dispositivo controlador 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 la
Permiso con privilegios de
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