O foreground service "caiu" após a atualização? Você não está sozinho
\nImagine: 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.
O que é startForeground e para que serve?
\nNo 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.
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.
Por que ocorre o startForeground fail no Android 8.1?
\nA 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.
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.
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\nComo corrigir: guia passo a passo em Kotlin
\nVamos reescrever seu serviço para que funcione no Android 8.1 e superior. Usaremos Kotlin — uma linguagem moderna e concisa.
\n\nPasso 1: Crie o canal de notificações
\nO 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:
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}\nObserve: verificamos a versão do SDK. Em dispositivos mais antigos, os canais não são necessários, e