As notificações fornecem informações curtas e oportunas sobre eventos no seu app enquanto ele não está em uso. Este documento mostra como criar uma notificação com vários recursos. Para uma introdução sobre como as notificações aparecem no Android, consulte a Visão geral de notificações. Para ver um exemplo de código que usa notificações, consulte o exemplo do SociaLite no GitHub.
O código nesta página usa as APIs NotificationCompat da biblioteca
AndroidX. Com essas APIs, é possível adicionar recursos disponíveis apenas em versões mais recentes do
Android, mantendo a compatibilidade com o Android 9 (nível 28 da API).
No entanto, alguns recursos, como a ação de resposta inline, resultam em uma operação nula em
versões anteriores.
Criar uma notificação básica
Uma notificação na forma mais básica e compacta, também conhecida como forma recolhida, mostra um ícone, um título e uma pequena quantidade de conteúdo de texto. Esta seção mostra como criar uma notificação que o usuário pode tocar para iniciar uma atividade no seu app.
Figura 1. Uma notificação com um ícone, um título e um texto.
Para mais detalhes sobre cada parte de uma notificação, leia sobre a anatomia da notificação.
Declarar a permissão de execução
O Android 13 (nível 33 da API) e versões mais recentes oferecem suporte a uma permissão de execução para postar notificações não isentas (incluindo serviços em primeiro plano, ou FGS) de um app.
O snippet de código abaixo mostra a permissão que precisa ser declarada no arquivo de manifesto do app:
<manifest ...> <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/> <application ...> ... </application> </manifest>
Para mais detalhes sobre as permissões de execução, consulte Permissão de execução de notificações.
Definir o conteúdo das notificações
Para começar, defina o conteúdo e o canal da notificação usando um objeto
NotificationCompat.Builder. O exemplo a seguir mostra como
criar uma notificação com o seguinte:
Um ícone pequeno, definido por
setSmallIcon(). Esse é o único conteúdo visível para o usuário que é obrigatório.Um título, definido por
setContentTitle().O corpo do texto, definido por
setContentText().A prioridade da notificação, definida por
setPriority(). A prioridade determina o nível de intrusão da notificação no Android 7.1 e versões anteriores. No Android 8.0 e versões mais recentes, defina a importância do canal, conforme mostrado na próxima seção.
val textTitle = "Title" val textContent = "Content" val builder = NotificationCompat.Builder(context, CHANNEL_ID) .setSmallIcon(R.drawable.ic_logo) .setContentTitle(textTitle) .setContentText(textContent) .setPriority(NotificationCompat.PRIORITY_DEFAULT)
O construtor NotificationCompat.Builder exige que você forneça um ID de canal. Isso é necessário para compatibilidade com o Android 8.0 (nível 26 da API) e
versões mais recentes, mas é ignorado por versões anteriores.
Por padrão, o conteúdo do texto da notificação é truncado para caber em uma única linha. Você pode mostrar mais informações criando uma notificação expansível.
Figura 2. Uma notificação expansível nas formas recolhida e expandida.
Se você quiser que a notificação seja mais longa, ative uma notificação expansível
adicionando um modelo de estilo com setStyle(). Por exemplo,
o código a seguir cria uma área de texto maior:
val builder = NotificationCompat.Builder(context, CHANNEL_ID) .setSmallIcon(R.drawable.ic_logo) .setContentTitle("My notification") .setContentText("Much longer text that cannot fit one line...") .setStyle(NotificationCompat.BigTextStyle() .bigText("Much longer text that cannot fit one line...")) .setPriority(NotificationCompat.PRIORITY_DEFAULT)
Para mais informações sobre outros estilos de notificação grandes, incluindo como adicionar uma imagem e controles de mídia, consulte Criar uma notificação expansível.
Criar um canal e definir a importância
Antes de enviar a notificação no Android 8.0 e versões mais recentes, registre o
canal de notificação do app no sistema transmitindo uma instância de
NotificationChannel para createNotificationChannel(). O
código abaixo é bloqueado por uma condição na versão SDK_INT:
fun createNotificationChannel(context: Context) { // Create the NotificationChannel, but only on API 26+ because // the NotificationChannel class is not in the Support Library. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val name = context.getString(R.string.channel_name) val descriptionText = context.getString(R.string.channel_description) val importance = NotificationManager.IMPORTANCE_DEFAULT val channel = NotificationChannel(CHANNEL_ID, name, importance).apply { description = descriptionText } // Register the channel with the system. val notificationManager: NotificationManager = context.getSystemService(NotificationManager::class.java) as NotificationManager notificationManager.createNotificationChannel(channel) } }
Como é necessário criar o canal de notificação antes de postar notificações no Android 8.0 e versões mais recentes, execute esse código quando o app for iniciado. É seguro chamar repetidamente porque criar um canal existente não faz nada.
O construtor NotificationChannel requer um nível de importância que use uma
constante NotificationManager. Isso determina como interromper o
usuário. Para oferecer suporte ao Android 7.1 e versões anteriores, defina também a prioridade com
setPriority(), conforme mostrado no exemplo anterior.
Embora seja necessário definir a importância ou a prioridade, o sistema não garante o comportamento do alerta. O sistema pode ajustá-lo com base em outros fatores, e o usuário sempre pode personalizar o nível de importância do canal.
Para saber mais sobre o significado dos diferentes níveis, leia sobre os níveis de importância da notificação.
Definir a ação de toque da notificação
Cada notificação precisa responder a um toque, geralmente para abrir uma atividade no
app que corresponda à notificação. Para fazer isso, especifique uma intent de conteúdo
definida com um objeto PendingIntent e transmita-a para
setContentIntent().
O seguinte snippet mostra como criar uma intent básica para abrir uma atividade quando o usuário toca na notificação:
// Create an explicit intent for an Activity in your app. val intent = Intent(context, AlertDetails::class.java).apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK } val pendingIntent: PendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE) val builder = NotificationCompat.Builder(context, CHANNEL_ID) .setSmallIcon(R.drawable.ic_logo) .setContentTitle("My notification") .setContentText("Hello World!") .setPriority(NotificationCompat.PRIORITY_DEFAULT) // Set the intent that fires when the user taps the notification. .setContentIntent(pendingIntent) .setAutoCancel(true)
Esse código chama setAutoCancel(), que remove a
notificação automaticamente quando o usuário toca nela.
As flags de intent no exemplo anterior preservam a experiência de navegação esperada pelo usuário depois que ele abre o app usando a notificação. Talvez você queira usá-lo dependendo do tipo de atividade que está iniciando, que pode ser um dos seguintes:
Uma atividade que existe exclusivamente para respostas à notificação. Não há motivo para o usuário navegar até essa atividade durante o uso normal do app. Portanto, a atividade inicia uma nova tarefa em vez de ser adicionada à tarefa e à backstack do app. Esse é o tipo de intent criado no exemplo anterior.
Uma atividade que existe no fluxo regular do seu app. Nesse caso, iniciar a atividade cria uma backstack para que as expectativas do usuário para os botões "Voltar" e "Para cima" sejam preservadas.
Mostrar a notificação
Para que a notificação apareça, chame
NotificationManagerCompat.notify(), transmitindo um ID exclusivo para a
notificação e o resultado de NotificationCompat.Builder.build(). Isso é mostrado neste exemplo:
with(NotificationManagerCompat.from(context)) { if (ActivityCompat.checkSelfPermission( context, Manifest.permission.POST_NOTIFICATIONS ) != PackageManager.PERMISSION_GRANTED ) { // TODO: Consider calling ActivityCompat#requestPermissions here // to request the missing permissions, and then overriding // public fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, // grantResults: IntArray) // to handle the case where the user grants the permission. See the documentation // for ActivityCompat#requestPermissions for more details. return@with } // notificationId is a unique int for each notification that you must define. notify(notificationId, builder.build())
Salve o ID de notificação que você transmitir para NotificationManagerCompat.notify(),
porque ele será necessário quando você quiser atualizar ou
remover a notificação.
Além disso, para testar notificações básicas em dispositivos com o Android 13 e versões mais recentes, ative as notificações manualmente ou crie uma caixa de diálogo para solicitar notificações.
Adicionar botões de ação
Uma notificação pode oferecer até três botões de ação que permitem ao usuário responder rapidamente, como adiar um lembrete ou responder a uma mensagem de texto. No entanto, esses botões de ação não podem duplicar a ação realizada quando o usuário toca na notificação.
Figura 3. Uma notificação com um botão de ação.
Para adicionar um botão de ação, transmita um PendingIntent para o método addAction(). Isso é como configurar a ação de toque padrão da notificação, mas,
em vez de iniciar uma atividade, você pode fazer outras coisas, como iniciar um
BroadcastReceiver que executa um job em segundo plano para que a
ação não interrompa o app que já está aberto.
Por exemplo, o seguinte código mostra como enviar uma transmissão a um receptor específico:
val ACTION_SNOOZE = "snooze" val snoozeIntent = Intent(context, MyBroadcastReceiver::class.java).apply { action = ACTION_SNOOZE putExtra(EXTRA_NOTIFICATION_ID, 0) } val snoozePendingIntent: PendingIntent = PendingIntent.getBroadcast(context, 0, snoozeIntent, PendingIntent.FLAG_IMMUTABLE) val builder = NotificationCompat.Builder(context, CHANNEL_ID) .setSmallIcon(R.drawable.ic_logo) .setContentTitle("My notification") .setContentText("Hello World!") .setPriority(NotificationCompat.PRIORITY_DEFAULT) .setContentIntent(pendingIntent) .addAction(R.drawable.snooze, context.getString(R.string.snooze), snoozePendingIntent)
Para mais informações sobre como criar um BroadcastReceiver para executar trabalho em segundo plano, consulte a Visão geral de transmissões.
Se você estiver tentando criar uma notificação com botões de reprodução de mídia, como pausar e pular faixas, consulte como criar uma notificação com controles de mídia.
Adicionar uma ação de resposta direta
A ação de resposta direta, introduzida no Android 7.0 (nível 24 da API), permite que os usuários insiram texto diretamente na notificação. O texto é enviado ao app sem abrir uma atividade. Por exemplo, você pode usar uma ação de resposta direta para permitir que os usuários respondam a mensagens de texto ou atualizem listas de tarefas na notificação.
Figura 4. Toque no botão "Responder" para abrir a entrada de texto.
A ação de "Resposta direta" aparece como um outro botão na notificação que abre uma entrada de texto. Quando o usuário termina de digitar, o sistema anexa a resposta de texto à intent especificada para a ação de notificação e envia a intent ao app.
Adicionar o botão de resposta
Para criar uma ação de notificação que ofereça suporte à resposta direta, siga estas etapas:
Crie uma instância de RemoteInput.Builder que possa ser adicionada à ação de notificação. O construtor dessa classe aceita uma string que o sistema usa como chave para a entrada de texto. O app usa essa chave para recuperar o texto da entrada.
// Key for the string that's delivered in the action's intent. val replyLabel: String = context.resources.getString(R.string.reply_label) val remoteInput: RemoteInput = RemoteInput.Builder(KEY_TEXT_REPLY).run { setLabel(replyLabel) build() }
Crie uma PendingIntent para a ação de resposta.
// Build a PendingIntent for the reply action to trigger. val replyPendingIntent: PendingIntent = PendingIntent.getBroadcast(context, conversationId, getMessageReplyIntent(conversationId), PendingIntent.FLAG_MUTABLE)
Anexe o objeto RemoteInput a uma ação usando
addRemoteInput().
// Create the reply action and add the remote input. val action: NotificationCompat.Action = NotificationCompat.Action.Builder(R.drawable.reply, context.getString(R.string.reply_label), replyPendingIntent) .addRemoteInput(remoteInput) .build()
Aplique a ação a uma notificação e emita a notificação.
// Build the notification and add the action.
val newMessageNotification = NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_message)
.setContentTitle(context.getString(R.string.title))
.setContentText(context.getString(R.string.content))
.addAction(action)
.build()
// Issue the notification.
NotificationManagerCompat.from(context).notify(notificationId, newMessageNotification)
O sistema solicita que o usuário insira uma resposta quando ele aciona a ação de notificação, conforme mostrado na Figura 4.
Recuperar entrada do usuário na resposta
Para receber a entrada do usuário na interface de resposta da notificação, chame
RemoteInput.getResultsFromIntent(), transmitindo a Intent recebida pela
BroadcastReceiver:
private fun getMessageText(intent: Intent): CharSequence? { return RemoteInput.getResultsFromIntent(intent)?.getCharSequence(KEY_TEXT_REPLY) }
Depois de processar o texto, atualize a notificação chamando
NotificationManagerCompat.notify() com o mesmo ID e tag, se usados. Isso é
necessário para ocultar a interface de resposta direta e confirmar ao usuário que a resposta
foi recebida e processada corretamente.
// Build a new notification, which informs the user that the system // handled their interaction with the previous notification. val repliedNotification = NotificationCompat.Builder(context, CHANNEL_ID) .setSmallIcon(R.drawable.message) .setContentText(context.getString(R.string.replied)) .build() // Issue the new notification. NotificationManagerCompat.from(context).notify(notificationId, repliedNotification)
Recuperar outros dados
O processamento de outros tipos de dados funciona de maneira semelhante com RemoteInput. O exemplo a seguir usa uma imagem como entrada.
val replyLabel: String = context.resources.getString(R.string.reply_label) val remoteInput: RemoteInput = RemoteInput.Builder(KEY_REPLY).run { setLabel(replyLabel) // Allow for image data types in the input. // This method can be used again to allow for other data types. setAllowDataType("image/*", true) build() }
Chame RemoteInput#getDataResultsFromIntent e extraia os dados correspondentes.
class ReplyReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { val dataResults = RemoteInput.getDataResultsFromIntent(intent, KEY_REPLY) val imageUri: Uri? = dataResults?.get("image/*") as? Uri if (imageUri != null) { // Extract the image context.contentResolver.openInputStream(imageUri)?.use { inputStream -> val bitmap = BitmapFactory.decodeStream(inputStream) // Display the image // ... } } } companion object { const val KEY_REPLY = "key_reply" const val KEY_TEXT_REPLY = "key_text_reply" } }
Ao trabalhar com essa nova notificação, use o contexto transmitido para o
método onReceive() do receptor.
Anexe a resposta à parte de baixo da notificação chamando
setRemoteInputHistory(). No entanto, se você estiver criando um app de mensagens,
crie uma notificação no estilo de mensagem e anexe a nova mensagem à
conversa.
Para mais conselhos sobre notificações de apps de mensagens, consulte a seção sobre práticas recomendadas para apps de mensagens.
Mostrar uma mensagem urgente
Seu app pode precisar exibir uma mensagem urgente e com limite de tempo, por exemplo, para uma chamada telefônica recebida ou um alarme tocando. Nessas situações, é possível associar uma intent de tela cheia à notificação.
Quando a notificação é invocada, os usuários veem uma das seguintes opções, dependendo do status de bloqueio do dispositivo:
- Se o dispositivo do usuário estiver bloqueado, uma atividade de tela cheia será exibida, cobrindo a tela de bloqueio;
- Se o dispositivo do usuário estiver desbloqueado, a notificação aparecerá de forma estendida, incluindo opções para interagir ou descartar a notificação.
O snippet de código a seguir demonstra como associar sua notificação a uma intent de tela cheia:
val fullScreenIntent = Intent(context, ImportantActivity::class.java) val fullScreenPendingIntent = PendingIntent.getActivity(context, 0, fullScreenIntent, PendingIntent.FLAG_IMMUTABLE) val builder = NotificationCompat.Builder(context, CHANNEL_ID) .setSmallIcon(R.drawable.ic_logo) .setContentTitle("My notification") .setContentText("Hello World!") .setPriority(NotificationCompat.PRIORITY_DEFAULT) .setFullScreenIntent(fullScreenPendingIntent, true)
Definir a visibilidade da tela de bloqueio
Para controlar o nível de detalhes visíveis na notificação na tela de bloqueio,
chame setVisibility() e especifique um dos seguintes valores:
VISIBILITY_PUBLIC: o conteúdo completo da notificação é mostrado na tela de bloqueio.VISIBILITY_SECRET: nenhuma parte da notificação é mostrada na tela de bloqueio.VISIBILITY_PRIVATE: apenas informações básicas, como o ícone da notificação e o título do conteúdo, são mostradas na tela de bloqueio. O conteúdo completo da notificação não é exibido.
Ao definir VISIBILITY_PRIVATE, você também pode fornecer uma versão alternativa do
conteúdo da notificação que oculta determinados detalhes. Por exemplo, um app de SMS
pode mostrar uma notificação com o texto "Você tem 3 novas mensagens de texto", mas
ocultar o conteúdo e os remetentes das mensagens. Para fornecer essa notificação
alternativa, primeiro crie a notificação alternativa com
NotificationCompat.Builder como de costume. Em seguida, anexe a notificação alternativa
à notificação normal com setPublicVersion().
Lembre-se de que o usuário sempre tem controle total sobre a visibilidade das notificações na tela de bloqueio e pode controlá-las com base nos canais de notificação do app.
Atualizar uma notificação
Para atualizar uma notificação depois de emiti-la, chame
NotificationManagerCompat.notify() novamente, transmitindo o mesmo ID usado
anteriormente. Se a notificação anterior for dispensada, uma nova será criada.
Se quiser, chame setOnlyAlertOnce() para que a notificação
interrompa o usuário com som, vibração ou dicas visuais apenas na
primeira vez que ela aparecer, e não nas atualizações posteriores.
Remover uma notificação
As notificações permanecem visíveis até que um dos seguintes casos aconteça:
- o usuário dispense a notificação;
- O usuário toca na notificação, se você chamar
setAutoCancel()ao criar a notificação. - Chame
cancel()para um ID de notificação específico. Esse método também exclui as notificações em andamento. - Chame
cancelAll(), que remove todas as notificações emitidas anteriormente. - A duração especificada expira, se você definir um tempo limite ao criar a
notificação, usando
setTimeoutAfter(). Se necessário, é possível cancelar uma notificação antes que o tempo limite especificado termine.
Práticas recomendadas para apps de mensagens
Considere as práticas recomendadas listadas aqui ao criar notificações para seus apps de mensagens e chat.
Usar MessagingStyle
No Android 7.0 (nível 24 da API) e versões mais recentes, o Android oferece um modelo de estilo de notificação
específico para conteúdo de mensagens. Usando a classe
NotificationCompat.MessagingStyle, é possível mudar vários dos
rótulos mostrados na notificação, incluindo o título da conversa,
as mensagens adicionais e a visualização de conteúdo da notificação.
O snippet de código abaixo demonstra como personalizar o estilo de uma notificação
usando a classe MessagingStyle.
val message1 = NotificationCompat.MessagingStyle.Message( messages[0].text, messages[0].time, messages[0].sender ) val message2 = NotificationCompat.MessagingStyle.Message( messages[1].text, messages[1].time, messages[1].sender ) notification = NotificationCompat.Builder(context, CHANNEL_ID) .setSmallIcon(R.drawable.ic_logo) .setStyle( NotificationCompat.MessagingStyle(Person.Builder().setName("Me").build()) .addMessage(message1) .addMessage(message2) ) .build()
A partir do Android 9.0 (nível 28 da API), também é necessário usar a classe
Person para conseguir uma renderização ideal da notificação
e dos avatares dela.
Ao usar NotificationCompat.MessagingStyle, faça o seguinte:
- Chame
MessagingStyle.setConversationTitle()para definir um título para grupos de chat com mais de duas pessoas. Um bom título de conversa pode ser o nome do grupo de chat ou, se não houver um nome, uma lista dos participantes da conversa. Sem isso, a mensagem pode ser confundida com uma conversa individual com o remetente da mensagem mais recente na conversa. - Use o método
MessagingStyle.setData()para incluir mensagens de mídia, como imagens. Os tipos MIME do padrão image/* são compatíveis.
Usar a Resposta Direta
A resposta direta permite que um usuário responda inline a uma mensagem.
- Depois que um usuário responder com a ação de resposta inline, use
MessagingStyle.addMessage()para atualizar a notificaçãoMessagingStyle. Não retire nem cancele a notificação. Não cancelar a notificação permite que o usuário envie várias respostas pela notificação. - Para tornar a ação de resposta inline compatível com o Wear OS, chame
Action.WearableExtender.setHintDisplayInlineAction(true). - Use o método
addHistoricMessage()para fornecer contexto a uma conversa de resposta direta adicionando mensagens históricas à notificação.
Ativar a Resposta Inteligente
- Para ativar a Resposta inteligente, chame
setAllowGeneratedResponses(true)na ação de resposta. Isso faz com que as respostas inteligentes fiquem disponíveis para os usuários quando a notificação é enviada para um dispositivo Wear OS. As respostas inteligentes são geradas por um modelo de machine learning totalmente no relógio, usando o contexto fornecido pela notificaçãoNotificationCompat.MessagingStyle. Nenhum dado é enviado para a Internet para gerar as respostas.
Adicionar metadados de notificação
- Atribua metadados de notificação para informar ao sistema como processar as notificações do app
quando o dispositivo estiver no modo Não perturbe. Por
exemplo, use o método
addPerson()ousetCategory(Notification.CATEGORY_MESSAGE)para substituir o modo Não Perturbe.