---
title: "Foreground Service no Android com Kotlin em 2026: tipos, permissões e alternativas"
url: "https://kotlin.dev.br/blog/foreground-service-android-kotlin-2026/"
markdown_url: "https://kotlin.dev.br/blog/foreground-service-android-kotlin-2026.MD"
description: "Quando usar foreground service no Android com Kotlin: foregroundServiceType, permissões, notificação obrigatória, limites de start em background e alternativas."
date: "2026-09-01"
author: "Karina Melo"
---

# Foreground Service no Android com Kotlin em 2026: tipos, permissões e alternativas

Quando usar foreground service no Android com Kotlin: foregroundServiceType, permissões, notificação obrigatória, limites de start em background e alternativas.


**Resposta rápida:** um **foreground service** é a forma oficial de manter um trabalho **contínuo, visível e iniciado pelo usuário** rodando quando o app não está em primeiro plano — navegação turn-by-turn, player de mídia, gravação, chamada, upload longo com progresso. Em Kotlin, o caminho é: declarar o service no manifesto com um `foregroundServiceType` honesto, pedir a permissão específica daquele tipo (`FOREGROUND_SERVICE_*`), chamar `ServiceCompat.startForeground()` **em poucos segundos** com uma notificação de canal apropriado, e encerrar assim que a tarefa acabar. Se o trabalho é **adiável** (sync, upload sem urgência, limpeza), não use foreground service: use [WorkManager](/blog/workmanager-kotlin-android-2026/). Se o trabalho é apenas reagir a um evento do servidor, use [FCM](/blog/fcm-notificacoes-push-android-kotlin-compose-2026/). Foreground service é a exceção justificada, não o padrão.

Poucas APIs Android geram tanto retrabalho quanto essa. O time coloca um service "para não morrer", o Play Console pede declaração de tipo, o Android 14+ recusa o `startForeground()` sem permissão coerente, o app leva `ForegroundServiceStartNotAllowedException` ao tentar iniciar em background, e a bateria vira reclamação na review. Este guia fecha a lacuna: quando o foreground service é a escolha certa, como implementá-lo em Kotlin sem gambiarra, e quais alternativas resolvem 80% dos casos que aparecem em code review.

Antes de fixar versões de biblioteca ou tipos de service, confira a [documentação oficial de foreground services](https://developer.android.com/develop/background-work/services/fgs) e a [política de foreground service do Google Play](https://support.google.com/googleplay/android-developer/answer/13392821). As regras mudam a cada release do Android — o raciocínio abaixo é estável, a lista de tipos não.

## Quando um foreground service é realmente necessário

Faça as três perguntas na ordem:

1. **O usuário iniciou explicitamente esta tarefa e espera que ela continue?** (tocou em "Gravar", "Iniciar rota", "Play")
2. **A tarefa é contínua e sensível a interrupção?** (parar no meio quebra o resultado)
3. **O usuário precisa ver que ela está acontecendo?**

Três "sim" → foreground service. Qualquer "não" → provavelmente existe algo melhor.

| Cenário | Escolha adequada |
|---|---|
| Player de áudio/vídeo em background | Foreground service (`mediaPlayback`) com [Media3](/blog/media3-exoplayer-compose-kotlin-2026/) |
| Navegação turn-by-turn | Foreground service (`location`) |
| Gravação de áudio/vídeo | Foreground service (`microphone` / `camera`) |
| Upload grande com progresso visível | Foreground service curto **ou** WorkManager com `setForeground()` |
| Sincronizar dados quando houver rede | [WorkManager](/blog/workmanager-kotlin-android-2026/) com constraints |
| Reagir a evento do servidor | [FCM](/blog/fcm-notificacoes-push-android-kotlin-compose-2026/) + trabalho curto |
| Tarefa em horário exato | `AlarmManager` |
| Trabalho ligado à tela aberta | Coroutine no `ViewModel` |

O antipadrão mais comum em apps brasileiros de campo (logística, vistoria, delivery) é usar foreground service permanente **só para "não perder dados"**. Na prática, [offline-first](/blog/android-offline-first-kotlin-2026/) com fila local + WorkManager entrega o mesmo resultado sem notificação eterna e sem risco de política.

## Manifesto: tipo, permissões e honestidade

O manifesto declara o que o service faz. Declarar tipo errado é motivo de rejeição na Play Store.

```xml
<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_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

    <application>
        <service
            android:name=".rota.RotaService"
            android:exported="false"
            android:foregroundServiceType="location" />
    </application>
</manifest>
```

Regras que economizam horas de depuração:

- **`FOREGROUND_SERVICE` sozinha não basta** desde o Android 14: cada tipo exige sua permissão irmã (`FOREGROUND_SERVICE_LOCATION`, `FOREGROUND_SERVICE_MEDIA_PLAYBACK`, `FOREGROUND_SERVICE_CAMERA`, `FOREGROUND_SERVICE_MICROPHONE`, `FOREGROUND_SERVICE_DATA_SYNC`, entre outros).
- **O tipo precisa ter a permissão de runtime correspondente concedida.** Um service `location` sem `ACCESS_FINE_LOCATION`/`ACCESS_COARSE_LOCATION` aprovada lança exceção no `startForeground()`. Trate isso com o mesmo cuidado descrito no guia de [permissões no Android](/blog/permissoes-android-kotlin-2026/).
- **`dataSync` não é curinga.** É o tipo com escrutínio mais alto na revisão da Play e com limites de tempo mais duros em versões recentes. Se o seu caso cabe em `dataSync`, quase sempre cabe melhor em WorkManager.
- **`exported="false"`** salvo necessidade real de outro app iniciar o service.

## Implementação em Kotlin

Um foreground service enxuto: recebe a intenção, sobe a notificação imediatamente, delega o trabalho para coroutines e se encerra sozinho.

```kotlin
class RotaService : Service() {

    private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)

    override fun onBind(intent: Intent?): IBinder? = null

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        when (intent?.action) {
            ACTION_PARAR -> {
                pararTudo()
                return START_NOT_STICKY
            }
        }

        // Precisa acontecer nos primeiros segundos após o start.
        ServiceCompat.startForeground(
            this,
            NOTIFICACAO_ID,
            construirNotificacao(progresso = null),
            ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION,
        )

        scope.launch {
            try {
                acompanharRota().collect { estado ->
                    atualizarNotificacao(estado)
                }
            } finally {
                withContext(Dispatchers.Main) { pararTudo() }
            }
        }

        return START_STICKY
    }

    private fun pararTudo() {
        scope.cancel()
        ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE)
        stopSelf()
    }

    override fun onDestroy() {
        scope.cancel()
        super.onDestroy()
    }

    companion object {
        const val NOTIFICACAO_ID = 4201
        const val ACTION_PARAR = "br.dev.kotlin.PARAR_ROTA"
    }
}
```

Pontos que costumam ser cobrados em code review:

- **Nunca bloqueie a thread principal** dentro do service. `onStartCommand()` roda na main thread; todo I/O vai para coroutines com dispatcher adequado (veja [coroutines em Kotlin](/blog/coroutines-kotlin/) e [Flow](/blog/kotlin-flow/)).
- **Cancele o escopo** em `onDestroy()` e ao parar — service vazado é fonte clássica de leak detectável com [LeakCanary](/blog/leakcanary-android-kotlin-memory-leaks-2026/).
- **`START_STICKY` não é garantia.** O sistema pode recriar o service com `intent` nulo; trate esse caminho ou prefira `START_NOT_STICKY` quando reiniciar sem contexto não faz sentido.
- **Ofereça uma ação de parar** na própria notificação. Usuário sem botão de saída vira desinstalação.

## A notificação obrigatória — e como não ser silenciado

A notificação do foreground service não é enfeite: é o contrato com o usuário.

```kotlin
private fun construirNotificacao(progresso: Int?): Notification {
    val pararIntent = PendingIntent.getService(
        this,
        0,
        Intent(this, RotaService::class.java).setAction(ACTION_PARAR),
        PendingIntent.FLAG_IMMUTABLE,
    )

    return NotificationCompat.Builder(this, CANAL_ROTA)
        .setContentTitle("Rota em andamento")
        .setContentText(progresso?.let { "Progresso: $it%" } ?: "Preparando rota")
        .setSmallIcon(R.drawable.ic_rota)
        .setOngoing(true)
        .setOnlyAlertOnce(true)
        .setCategory(NotificationCompat.CATEGORY_NAVIGATION)
        .addAction(R.drawable.ic_stop, "Parar", pararIntent)
        .setContentIntent(abrirTelaDaRota())
        .build()
}
```

Boas práticas:

- **Canal próprio**, de importância baixa/média, separado do canal de marketing. O usuário deve poder silenciar promoções sem matar a visibilidade da tarefa.
- **`setOnlyAlertOnce(true)`** para atualizações de progresso não vibrarem a cada segundo.
- **Atualize com parcimônia** — atualizar notificação em loop apertado custa bateria e aparece em profiling ([Android Studio Profiler](/blog/android-studio-profiler-cpu-memory-network-kotlin-2026/)).
- **`POST_NOTIFICATIONS` no Android 13+** afeta a exibição; o service ainda roda, mas o usuário perde a pista visual. Peça a permissão no contexto certo.
- **Nada de dado sensível** no texto visível na tela de bloqueio — vale a mesma disciplina de [LGPD em apps Android](/blog/lgpd-android-kotlin-2026/).

## Limites de início em background

Esta é a origem da maioria dos crashes do tipo `ForegroundServiceStartNotAllowedException`: desde o Android 12, **um app em background não pode simplesmente iniciar um foreground service**. Existem exceções (o app está visível, o usuário acabou de interagir, há uma notificação de alta prioridade com ação do usuário, o dispositivo recebeu um `exact alarm` etc.), mas a regra prática é:

> Inicie o foreground service a partir de uma ação clara do usuário, com o app visível — ou não o inicie.

Se você recebeu um push e quer subir um service, pense duas vezes. Na maioria dos casos o correto é:

1. exibir uma notificação com ação ("Retomar download");
2. iniciar o service quando o usuário tocar;
3. ou enfileirar o trabalho em WorkManager, que sabe negociar com o sistema.

Ainda assim, blinde o código:

```kotlin
fun iniciarRotaComSeguranca(context: Context) {
    val intent = Intent(context, RotaService::class.java)
    try {
        ContextCompat.startForegroundService(context, intent)
    } catch (e: Exception) {
        // Android 12+: pode falhar se o app não estiver em estado permitido.
        agendarFallbackComWorkManager(context)
    }
}
```

Registre a falha na sua telemetria de estabilidade ([Crashlytics e ANR](/blog/firebase-crashlytics-anr-android-kotlin-2026/)) para saber com que frequência o caminho de exceção acontece em produção — normalmente é bem mais do que o time imagina.

## WorkManager com `setForeground()`: o meio-termo

Quando o trabalho é longo, tem progresso e o usuário iniciou, mas você quer as garantias de retry e constraints do WorkManager, use `CoroutineWorker` com `setForeground()`:

```kotlin
class UploadWorker(
    context: Context,
    params: WorkerParameters,
) : CoroutineWorker(context, params) {

    override suspend fun doWork(): Result {
        setForeground(criarForegroundInfo(progresso = 0))
        return try {
            enviarArquivos { progresso ->
                setForeground(criarForegroundInfo(progresso))
            }
            Result.success()
        } catch (e: IOException) {
            Result.retry()
        }
    }

    private fun criarForegroundInfo(progresso: Int) = ForegroundInfo(
        UPLOAD_ID,
        construirNotificacaoUpload(progresso),
        ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC,
    )
}
```

Vantagem: você herda backoff, constraints de rede/bateria e observabilidade do WorkManager, mas mostra progresso enquanto o trabalho está ativo. Desvantagem: continua sujeito às políticas de `dataSync`. Para uploads que podem esperar, remova o foreground e deixe o WorkManager decidir a janela.

## Bateria, Doze e a realidade dos OEMs

No Brasil, boa parte da base usa aparelhos com gerenciadores de bateria agressivos além do Doze do Android puro. Consequências práticas:

- Um foreground service **pode** ser encerrado por gerenciadores agressivos, mesmo sendo legítimo. Projete para retomar, não para assumir continuidade.
- **Persista o estado** a cada marco (não a cada tick): o usuário reabre o app e a tarefa continua de onde parou. Uma fila local resolve isso melhor do que memória do service.
- **Não peça isenção de otimização de bateria como padrão.** Pedir para todo mundo é sinal de arquitetura errada e queima confiança.
- Meça o custo real: `dumpsys` de bateria, [StrictMode](/blog/strictmode-android-kotlin-performance-2026/) para I/O indevido na main thread e [JankStats](/blog/jankstats-android-kotlin-compose-2026/) para o impacto na UI enquanto o service roda.

## Testes e verificação antes do release

Checklist mínimo:

1. `startForeground()` acontece nos primeiros segundos em todos os caminhos de start;
2. `foregroundServiceType` do manifesto bate com o passado em código;
3. permissões de runtime do tipo estão concedidas antes do start;
4. iniciar com o app em background falha de forma controlada, sem crash;
5. rotação e reinício do processo não duplicam o service;
6. ação "Parar" na notificação encerra e remove tudo;
7. bateria e memória estáveis em sessão longa;
8. sem leaks após o `stopSelf()`.

Para o fluxo do usuário (iniciar, ver notificação, voltar à tela correta), testes instrumentados com [Espresso](/blog/espresso-android-kotlin-testes-ui-2026/) cobrem a navegação; para a lógica interna, extraia o trabalho para classes puras testáveis e deixe o service como casca fina — o mesmo princípio de [modularização Android](/blog/modularizacao-android-kotlin-compose-2026/).

## Erros comuns

- **Service permanente "por segurança"** — a solução real é fila local + WorkManager.
- **Tipo de service inflado** (`dataSync` para tudo) — risco direto de rejeição na Play.
- **Chamar `startForeground()` tarde** — o sistema mata o processo com `ANR`/crash.
- **Notificação sem ação de parar** — o usuário desinstala em vez de pausar.
- **Escopo de coroutine não cancelado** — leak silencioso e trabalho zumbi.
- **Assumir que `START_STICKY` garante ressurreição** — não garante em todos os OEMs.
- **Iniciar service a partir de push** sem interação — exceção em Android 12+.
- **Ignorar `POST_NOTIFICATIONS`** — tarefa invisível vira reclamação de "app travado".

## Onde isso pesa na carreira Android

Foreground service é assunto de entrevista sênior justamente porque exige julgamento, não decoreba: você precisa argumentar por que **não** usou, quando usou, e como o produto se comporta quando o sistema encerra o processo. Vale colocar no portfólio um app com um fluxo real (gravação, upload com progresso ou player) documentando tipo escolhido, permissões e estratégia de retomada. Combine com o [roadmap Android](/carreira/roadmap-dev-android/) e acompanhe as [vagas Kotlin](/vagas/) — descrições de vaga de Android sênior citam `ForegroundService` ao lado de WorkManager e Coroutines com frequência.

## Perguntas frequentes

### Foreground service impede o Android de matar meu app?

Não. Ele reduz muito a probabilidade e dá prioridade maior ao processo, mas em pressão de memória extrema ou com gerenciadores agressivos de OEM o processo ainda pode cair. Projete para retomar estado, não para nunca morrer.

### Posso usar foreground service para sincronizar dados a cada 15 minutos?

Esse é exatamente o caso do WorkManager com trabalho periódico e constraints. Um foreground service permanente para sync periódico tende a ser reprovado na revisão da Play e queima bateria sem necessidade.

### Qual a diferença entre foreground service e WorkManager com `setForeground()`?

O service é você gerenciando ciclo de vida diretamente. O `CoroutineWorker` com `setForeground()` mostra a mesma notificação, mas roda dentro do WorkManager, herdando retry, constraints e observabilidade. Para trabalho iniciado pelo usuário com fim previsível, o worker costuma ser o caminho mais barato de manter.

### Preciso mesmo declarar `foregroundServiceType`?

Sim para versões recentes do Android, e a declaração precisa ser verdadeira e coerente com as permissões concedidas. Declaração genérica ou incorreta gera exceção em runtime e problema de política na loja.

### Como testar o comportamento em background restrito?

Use as opções de desenvolvedor para limitar processos em background, force Doze via `adb shell dumpsys deviceidle force-idle`, e teste em pelo menos um aparelho com gerenciador agressivo de bateria além do emulador. O comportamento no Pixel não representa a base brasileira inteira.

## Conclusão e próximos passos

Foreground service é uma ferramenta cirúrgica: excelente para trabalho contínuo, visível e iniciado pelo usuário; péssima como muleta contra as regras de background do Android. O caminho saudável em Kotlin é service fino, notificação honesta com ação de parar, tipo declarado com precisão, coroutines canceláveis e estado persistido para retomada.

Próximos passos no cluster Android deste site:

1. revisar o modelo de trabalho adiável em [WorkManager](/blog/workmanager-kotlin-android-2026/);
2. alinhar o momento de pedir [permissões](/blog/permissoes-android-kotlin-2026/), inclusive `POST_NOTIFICATIONS`;
3. tratar o sinal do servidor com [FCM](/blog/fcm-notificacoes-push-android-kotlin-compose-2026/) em vez de service eterno;
4. medir impacto com [StrictMode](/blog/strictmode-android-kotlin-performance-2026/), [JankStats](/blog/jankstats-android-kotlin-compose-2026/) e o [guia de performance](/guias/guia-kotlin-performance/);
5. garantir que a fila local segue [offline-first](/blog/android-offline-first-kotlin-2026/) e não depende do service estar vivo.
