Saltar al contenido
Todas las entradas

Tipos de servicio en primer plano en Android en 2026: elegir el que realmente encaja con tu función

Una guía práctica sobre las restricciones de tipos de servicio en primer plano de Android — dataSync, mediaPlayback, specialUse, shortService — y cómo elegir el correcto sin que te lo maten o te lo rechacen.

MFKAPPS 6 min de lectura

Antes, iniciar un servicio en primer plano era una línea de código y una notificación. Ya no. Todo servicio en primer plano en un SDK objetivo actual tiene que declarar un tipo en el manifiesto, pedir el permiso correspondiente y, en un par de casos, justificar su propia existencia ante Google antes de que la app se publique. Nada de esto es burocracia por capricho — cada tipo lleva una garantía de vida distinta, y elegir el tipo equivocado es la forma en que una función que funcionaba bien en pruebas termina muerta en silencio en un dispositivo real semanas después. Aquí va cómo elegir de verdad, usando como ejemplo la decisión que tuvo que tomar el temporizador de enfoque de Mintly.

Por qué “simplemente iniciar un servicio en primer plano” dejó de funcionar

El modelo antiguo era permisivo: llamabas a startForeground(), mostrabas una notificación y el sistema básicamente te dejaba en paz mientras la notificación siguiera visible. Eso convirtió a los servicios en primer plano en un imán para el abuso — un servicio de “sincronización” que nunca sincronizaba nada, un servicio de “escucha” que solo mantenía vivo el proceso. La respuesta de la plataforma ha sido atar cada servicio en primer plano a un tipo declarado, cada uno con su propio permiso y su propio contrato sobre cuánto tiempo puede correr sin supervisión. Ya no puedes decir “confía en mí, esto es importante”. Dices qué clase de importante, y el sistema hace cumplir el resto.

<service
    android:name=".timer.FocusSessionService"
    android:foregroundServiceType="specialUse"
    android:exported="false">
    <property
        android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
        android:value="active-focus-timer" />
</service>

Si omites la declaración del tipo, el servicio simplemente no arrancará en un SDK objetivo actual — startForeground() lanza una excepción, no se limita a avisar.

Los tipos que realmente encajan con la mayoría de funciones indie

La lista seleccionada cubre casos como camera, microphone, location, phoneCall, mediaPlayback y connectedDevice — cada uno acotado estrictamente a lo que su nombre sugiere, cada uno protegido por un permiso que corresponde a la capacidad real (FOREGROUND_SERVICE_CAMERA necesita CAMERA, y así sucesivamente). Si tu función realmente reproduce audio o transmite desde un dispositivo conectado, el tipo es obvio y el permiso probablemente ya lo tienes.

Los dos tipos que merece la pena entender más a fondo son los que no se mapean a un sensor único: dataSync y specialUse.

dataSync es para una transferencia en segundo plano con una línea de meta clara — subir una copia de seguridad, traer una actualización remota. No es un estado de reposo; desde Android 15, los servicios dataSync y mediaProcessing tienen un presupuesto de tiempo de ejecución acumulado de aproximadamente seis horas en una ventana móvil de 24 horas. Si lo superas, el sistema llama a Service.onTimeout(), dándote un breve margen para terminar antes de forzar el cierre del servicio. Es un intercambio razonable para lo que el tipo está pensado — una transferencia que se supone que termina — y un mal encaje para algo pensado para quedarse ahí indefinidamente.

specialUse: el tipo para todo lo que no está en la lista

Un temporizador de enfoque de 25 minutos no es una sincronización de datos, ni reproducción multimedia, ni está ligado a un sensor. Es exactamente el hueco que specialUse existe para cubrir — un servicio en primer plano que está genuinamente limitado en el tiempo e iniciado por el usuario, pero que no encaja en ninguna de las categorías con nombre. La trampa es que no puedes simplemente declararlo y seguir adelante: la etiqueta <property> del manifiesto exige una cadena de subtipo que describa lo que hace el servicio, y la revisión de la app en Google Play lee esa cadena. Declara specialUse para algo que en realidad es una sincronización de datos disfrazada o un truco para mantenerse vivo, y ese es exactamente el tipo de desajuste que se marca durante la revisión, no después del lanzamiento.

Para Mintly, el subtipo es active-focus-timer, y el formulario de declaración de servicio en primer plano de la Play Console dice lo mismo en inglés sencillo: una sesión en curso que el usuario inició y está observando activamente, que termina en un momento específico. Es un caso fácil de justificar porque es verdad. Escribir una descripción honesta de una línea de lo que hace el servicio es tiempo mejor invertido que intentar encontrar un tipo que esquive el escrutinio de la revisión.

shortService: construido para la ráfaga, no para la sesión

El otro tipo que conviene conocer es shortService, pensado para un servicio en primer plano que solo necesita un par de minutos para terminar algo — escribir una exportación grande, ejecutar una limpieza puntual — menos tiempo del que los usuarios tolerarían el arranque en frío de un trabajo acelerado de WorkManager. Viene con un límite de ejecución estricto de unos tres minutos; el sistema no negocia más allá de eso, y el tipo existe precisamente para que el trabajo de corta duración deje de abusar de dataSync o specialUse para conseguir más margen del que necesita. Si tu tarea termina de forma predecible en menos de tres minutos, este es el tipo honesto que hay que usar. Si a veces se alarga, no es el correcto, y lo descubrirás en producción, no en pruebas.

Elegir mal el tipo es un bug de producción, no un aviso del linter

El tipo que declaras no es un metadato que Android ignore educadamente si no estás seguro. Declara dataSync para algo que corre ocho horas al día y se le acabará el tiempo a mitad de ejecución — un estado que tu app luego tiene que detectar y del que recuperarse correctamente, o el usuario simplemente verá una función atascada sin ninguna explicación. Declara specialUse sin un subtipo honesto y la revisión de Play puede rechazar la actualización directamente, lo cual es un retraso de lanzamiento mucho peor que los diez minutos que cuesta elegir el tipo correcto desde el principio.

La decisión se reduce a dos preguntas: ¿este servicio corresponde a una capacidad real como camera o mediaPlayback? Si no, ¿el trabajo está naturalmente acotado en minutos (shortService), en horas con un final claro (dataSync), o es abierto pero iniciado por el usuario y observado activamente (specialUse, declarado con honestidad)? Responde a eso antes de escribir la entrada del manifiesto, no después de que aparezca el informe de fallos. El sistema de tipos es molesto de aprender una vez, y luego es solo un hecho sobre la plataforma — igual que las Live Updates de Android 16 se asientan sobre el servicio del temporizador de Mintly en lugar de sustituir la necesidad de elegir bien su tipo de servicio en primer plano desde el principio.