Falha no startForeground após atualização para Android 8.1: solução em Kotlin

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

O foreground service "caiu" após a atualização? Você não está sozinho

\n

Imagine: você inicia seu aplicativo, ele deve funcionar em segundo plano, exibindo uma notificação importante. Tudo funcionava perfeitamente no Android 7.0, os usuários estavam satisfeitos. Mas então sai a atualização para Android 8.1 — e o aplicativo trava com o erro misterioso startForeground fail. Familiar? Se você já enfrentou esse problema, sabe como ele desestabiliza. No Stack Overflow, essa pergunta acumulou milhares de visualizações, o que significa que afetou muitos desenvolvedores. Neste artigo, vamos entender por que isso acontece, como corrigir o erro em Kotlin e, principalmente, como evitá-lo no futuro.

\n\n

O que é startForeground e para que serve?

\n

No Android, o foreground service (serviço em primeiro plano) é um serviço que executa ações perceptíveis ao usuário. Por exemplo, reprodução de música, gravação de rota GPS ou download de arquivo. Diferente de um serviço comum, o foreground service é obrigado a exibir uma notificação permanente na barra de status. Isso é feito através da chamada startForeground(), que recebe um ID de notificação e o próprio objeto Notification.

\n

A partir do Android 8.0 (API 26), o Google introduziu restrições rigorosas para serviços em segundo plano. Agora, se você tentar iniciar um foreground service sem uma notificação configurada corretamente, o sistema lançará uma exceção ForegroundServiceStartNotAllowedException ou simplesmente ignorará a chamada. No Android 8.1, essas restrições se tornaram ainda mais rígidas, e o erro startForeground fail se tornou massivo.

\n\n

Por que ocorre o startForeground fail no Android 8.1?

\n

A principal causa é a ausência ou configuração incorreta do canal de notificações (Notification Channel). Antes do Android 8.0, as notificações podiam ser criadas sem canais. Após a atualização, o Google obrigou os desenvolvedores a criar pelo menos um canal para cada tipo de notificação. Se você chamar startForeground() com uma notificação que não possui canal, o sistema simplesmente não sabe como exibi-la e lança um erro.

\n

A segunda causa é a violação de tempo. Você deve chamar startForeground() dentro dos primeiros 5 segundos após iniciar o serviço. Se não fizer isso, o serviço será encerrado e o aplicativo pode travar.

\n

A terceira causa é a tentativa de iniciar o serviço a partir do segundo plano. A partir do Android 8.0, iniciar um foreground service a partir de um contexto em segundo plano (por exemplo, de um BroadcastReceiver ou de outro serviço) é proibido. A exceção é apenas se o aplicativo estiver em primeiro plano.

\n\n

Como corrigir: guia passo a passo em Kotlin

\n

Vamos reescrever seu serviço para que funcione no Android 8.1 e superior. Usaremos Kotlin — uma linguagem moderna e concisa.

\n\n

Passo 1: Crie o canal de notificações

\n

O canal deve ser criado antes de você exibir a notificação. O melhor lugar é no método onCreate() do seu serviço ou na classe Application. Veja o exemplo:

\n
class MyForegroundService : Service() {\n    companion object {\n        const val CHANNEL_ID = "my_foreground_channel"\n        const val NOTIFICATION_ID = 1\n    }\n\n    override fun onCreate() {\n        super.onCreate()\n        createNotificationChannel()\n    }\n\n    private fun createNotificationChannel() {\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {\n            val channel = NotificationChannel(\n                CHANNEL_ID,\n                "Canal do Foreground Service",\n                NotificationManager.IMPORTANCE_LOW\n            ).apply {\n                description = "Canal para notificações do foreground service"\n            }\n            val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager\n            notificationManager.createNotificationChannel(channel)\n        }\n    }\n}
\n

Observe: verificamos a versão do SDK. Em dispositivos mais antigos, os canais não são necessários, e

Blogs

Book Recommendations