Como usar as notificações do Android

Este codelab faz parte do curso Android avançado no Kotlin. Você aproveitará mais o curso se fizer os codelabs em sequência, mas isso não é obrigatório. Todos os codelabs do curso estão listados na página de destino dos codelabs avançados do Android em Kotlin (link em inglês).

Introdução

As notificações são mensagens mostradas ao usuário fora da IU do app. As notificações serão exibidas na parte superior da tela se o dispositivo estiver desbloqueado ou, dependendo das configurações de segurança, na tela de bloqueio quando o dispositivo estiver bloqueado.

Uma notificação típica consiste em um título, uma descrição e um ícone. Uma notificação também pode ter ações clicáveis, uma resposta rápida, conteúdo extensível e imagens.

As notificações podem apresentar material oportuno e podem ter botões que permitam ao usuário realizar ações rápidas, como enviar uma resposta ou adiar um alarme. Ao clicar em uma notificação, o usuário é direcionado a uma visualização no app relacionada ao conteúdo.

As notificações são uma maneira útil de lembrar os usuários de uma tarefa importante, informar que algo aconteceu ou comunicar informações importantes imediatamente enquanto o app está em segundo plano. Use as notificações com moderação. Isso não só respeita os usuários, mas também torna mais provável que a notificação do seu app receba a atenção que ele merece.

Neste codelab, você aprenderá a criar e usar notificações em um app Android.

O que você já precisa saber

Você precisa:

  • Como criar apps Android em Kotlin. Especificamente, trabalhe com o SDK do Android.
  • Como arquitetar apps usando os Componentes da arquitetura e a vinculação de dados.
  • Entendimento básico de BroadcastReceivers
  • Entendimento básico do AlarmManager

O que você vai aprender

  • Como criar, definir o estilo e enviar uma notificação.
  • Como cancelar notificações.
  • Como criar canais de notificação.
  • Como adicionar ações rápidas às notificações.
  • Como exibir ícones de notificação no ícone do app.

Atividades do laboratório

  • Adicione uma notificação ao app inicial.
  • Cancele a notificação que você enviou.
  • Crie canais para diferentes tipos de notificações.
  • Personalize as notificações no app inicial.
  • Adicione ações rápidas para tornar a notificação interativa.
  • Desative os selos de notificação.

Cozinhar ovos é simples, mas pode ser uma tarefa desafiadora se você não monitorar o tempo. Neste codelab, você trabalhará em um app de timer de ovo e será perfeito, assim como seus ovos futuros. Você começará com um app de timer de ovo funcional que permite ao usuário definir diferentes configurações de tempo de cozimento para diferentes estilos de ovos. O timer fará a contagem regressiva do intervalo de tempo selecionado e exibirá uma mensagem de aviso quando os ovos estiverem prontos.

Pode parecer funcional, mas está longe de ser perfeito e de não ser fácil de usar. Para começar, a mensagem de aviso é mostrada apenas por um breve período e, portanto, é fácil de esquecer. Além disso, se o aplicativo não estiver em primeiro plano ou o dispositivo estiver bloqueado, não haverá um indicador visual para o status do timer quando a mensagem de aviso desaparecer.

O ideal é que o timer do ovo use notificações para informar aos usuários quando o tempo se esgotar. O usuário precisa saber que os ovos estão prontos de outra forma, caso contrário, eles serão preparados! As notificações são visuais, podem incluir sons e podem fazer o dispositivo vibrar. Isso é tudo que chama a atenção do usuário. Assim, você pode alcançar ovos perfeitos e usuários satisfeitos e bem alimentados.

Para fazer o download do app de exemplo:

Clone o repositório do GitHub e mude para a ramificação starter.

$  git clone https://github.com/googlecodelabs/android-kotlin-notifications


Como alternativa, é possível fazer o download do repositório como um arquivo ZIP, descompactá-lo e abri-lo no Android Studio.

Fazer o download do ZIP

  1. Abra e execute o app no Android Studio.

Você verá uma imagem de ovo e um menu suspenso com uma lista de intervalos de tempo predefinidos para cozinhar um ovo. Clique no triângulo do menu suspenso Soft Boiled. A primeira opção da lista é fornecida para fins de teste e define o alarme para apenas 10 segundos. Ao lado da lista, há um interruptor que inicia o timer do ovo. Você pode usar este interruptor para iniciar e parar o timer de quando quiser. O código inicial é totalmente funcional, o que significa que você pode configurar o timer do ovo e observar a contagem como 0. Quando o timer terminar, uma mensagem de aviso será exibida, conforme mostrado abaixo.

  1. Inspecionar o código-fonte. O app inicial consiste em uma única atividade chamada MainActivity. Há três subpacotes com o nome receiver, ui e util.

  • /receiver: o pacote receiver contém dois broadcast receivers chamados AlarmReceiver e SnoozeReceiver. AlarmReceiver é acionado pelo AlarmManager para enviar a notificação quando o timer definido pelo usuário estiver ativo. SnoozeReceiver gerencia o clique do usuário para adiar a notificação.
  • /ui: contém a EggTimerFragment, que faz parte da parte da IU do app. O EggTimerViewModel é responsável por iniciar e cancelar o timer e por outras tarefas do app relacionadas ao ciclo de vida.
  • /util: neste pacote há dois arquivos. BindingUtils.kt tem adaptadores de vinculação para ativar a vinculação de dados entre a IU do app e o ViewModel. NotificationUtils.kt tem métodos de extensão na NotificationManager.

O uso de notificações é uma ótima maneira de chamar a atenção dos usuários para o app. Se o app não estiver em execução ou em primeiro plano, uma notificação mostrará uma janela pop-up na parte superior da tela e pode incluir som ou vibração. Para criar uma notificação, é necessário usar um criador de notificações e fornecer um texto de título, um texto de conteúdo e um ícone. Quando o builder tiver todos os campos necessários, o NotificationManager, que é um serviço do sistema, ajuda a exibir esse conteúdo como uma notificação. O NotificationManager é responsável por enviar uma notificação, atualizar seu conteúdo e cancelá-la. Nas etapas a seguir, você adicionará métodos de extensão a NotificationManager. Dessa forma, sempre que você precisar usar NotificationManager, poderá usar as funções de extensão para ter a funcionalidade necessária.

Etapa 1: criar uma notificação básica

Nesta tarefa, você vai criar uma notificação, definir uma mensagem para o usuário e enviar a notificação.

  1. Abra a classe NotificationUtils.kt e localize TODO: Step 1.1. Neste codelab, você encontrará o código correspondente do app e todo o conteúdo correspondente.
  2. Examina a função sendNotification() especificada. Você estenderá essa função de extensão para o NotificationManager para enviar notificações.
//NotificationUtils.kt
// TODO: Step 1.1 extension function to send messages (GIVEN)
/**
 * Builds and delivers a notification.
 *
 * @param messageBody, notification text.
 * @param context, activity context.
 */
fun NotificationManager.sendNotification(messageBody: String, applicationContext: Context) {
  1. Receba uma instância do criador de notificações, transmita o contexto do aplicativo e um ID do canal. O ID do canal é um valor de string do canal.

Canais de notificação são uma forma de agrupar notificações. Ao agrupar tipos semelhantes de notificações, os desenvolvedores e usuários podem controlar todas as notificações no canal. Depois de ser criado, o canal pode ser usado para enviar qualquer número de notificações.

//NotificationUtils.kt
// TODO: Step 1.2 get an instance of NotificationCompat.Builder
val builder = NotificationCompat.Builder(
        applicationContext,
        applicationContext.getString(R.string.egg_notification_channel_id)
)
  1. Defina o ícone de notificação para representar seu app, um título e o texto do conteúdo da mensagem que você quer transmitir ao usuário. Você verá mais opções para personalizar ainda mais as notificações no codelab, mas essa é a quantidade mínima de dados que precisam ser definidas para enviar uma notificação.
//NotificationUtils.kt
   // TODO: Step 1.3 set title, text and icon to builder
   .setSmallIcon(R.drawable.cooked_egg)
   .setContentTitle(applicationContext.getString(R.string.notification_title))
   .setContentText(messageBody)
  1. Em seguida, é necessário chamar notify() com um ID exclusivo para sua notificação e com o objeto Notification do builder.

Esse ID representa a instância de notificação atual e é necessário para atualizar ou cancelar essa notificação. Como seu app terá apenas uma notificação ativa por vez, você pode usar o mesmo ID para todas elas. Você já recebe uma constante para essa finalidade chamada NOTIFICATION_ID em NotificationUtils.kt. Observe que você pode chamar diretamente notify() porque está fazendo a chamada de uma função de extensão na mesma classe.

//NotificationUtils.kt
   // TODO: Step 1.4 call notify to send the notification
    // Deliver the notification
    notify(NOTIFICATION_ID, builder.build())
  1. Abra ui/EggTimerViewModel.kt e localize a função startTimer(). Essa função cria um alarme com o intervalo de tempo selecionado quando o usuário ativa o timer do ovo.
  2. Você acionará uma notificação nessa função quando o usuário iniciar o timer. Para chamar a função sendNotification() implementada anteriormente, você precisa de uma instância de NotificationManager. O NotificationManager é um serviço do sistema que oferece todas as funções expostas para a API de notificações, incluindo a função de extensão adicionada. Sempre que você quiser enviar, cancelar ou atualizar uma notificação, precisará solicitar uma instância do NotificationManager ao sistema. Chame a função sendNotification()| com a mensagem de notificação e o contexto.
// EggTimerViewModel.kt
// TODO: Step 1.5 get an instance of NotificationManager 
// and call sendNotification

val notificationManager = ContextCompat.getSystemService(
    app, 
    NotificationManager::class.java
) as NotificationManager
                notificationManager.sendNotification(app.getString(R.string.timer_running), app)

Quase lá. No entanto, se você executar o app agora e definir o timer, não receberá uma notificação.

  1. Abra o arquivo logcat e pesquise "No Channel found". Você verá uma mensagem de erro informando que egg_channel não existe. Nas etapas a seguir, você aprenderá mais sobre os canais de notificação e corrigirá esse problema.

Etapa 2: canais de notificação

A partir do nível 26 da API, todas as notificações precisam ser atribuídas a um canal. Se você tocar no ícone do app na tela de início e mantê-lo pressionado, selecione as informações do app e toque em notificações para ver uma lista de canais de notificação associados ao app. Neste momento, a lista está vazia porque seu app não criou nenhum canal.

Os canais representam um tipo de notificação; por exemplo, o timer do ovo pode enviar uma notificação quando o ovo estiver cozido, além de usar outro canal para enviar notificações diárias para lembrá-lo de ter ovos com seu café da manhã. Todas as notificações de um canal são agrupadas, e os usuários podem definir as configurações de notificação para um canal inteiro. Isso permite que os usuários personalizem as configurações de notificação com base no tipo de notificação em que estão interessados. Por exemplo, os usuários podem desativar as notificações de café da manhã, mas ainda optarem por vê-las no timer.

Os desenvolvedores definem as configurações iniciais, a importância e o comportamento para serem aplicadas a todas as notificações em um canal. Depois que você definir as configurações iniciais, os usuários poderão substituí-las.

Na Etapa 1.1, você usou o egg_notification_channel_id como seu canal de notificação. Portanto, agora você precisa criar e personalizar as configurações e o comportamento desse canal.

  1. Abra EggTimerFragment.kt e localize a função createChannel().
  2. Transmita o ID exclusivo do canal para o construtor de NotificationChannel.
  3. Transmita o nome do canal de notificação que os usuários também verão na tela Configurações.
  4. Como o último parâmetro, transmita o nível de importância do canal de notificação. Os níveis de importância serão abordados mais adiante neste codelab. Assim, você pode usar o NotificationManager.IMPORTANCE_LOW.
  5. No objeto notificationChannel, defina enableLights como verdadeiro. Esta configuração ativará as luzes quando uma notificação for exibida.
  6. No objeto notificationChannel, defina lightColor como vermelho para exibir uma luz vermelha quando uma notificação for exibida.
  7. No objeto notificationChannel, defina enableVibration como verdadeiro para ativar a vibração.
  8. No objeto notificationChannel, defina a descrição do canal como ‘Time for breakfast'.
  9. Para receber uma instância de NotificationManager, chame getSystemService().
  10. Chame createNotificationChannel() em NotificationManager e transmita o objeto notificationChannel que você criou na etapa anterior.
//EggTimerFragment.kt
private fun createChannel(channelId: String, channelName: String) {
    // TODO: Step 1.6 START create a channel
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val notificationChannel = NotificationChannel(
            channelId,
            channelName,
            // TODO: Step 2.4 change importance
            NotificationManager.IMPORTANCE_LOW
        )
        // TODO: Step 2.6 disable badges for this channel

        notificationChannel.enableLights(true)
        notificationChannel.lightColor = Color.RED
        notificationChannel.enableVibration(true)
        notificationChannel.description = "Time for breakfast"

        val notificationManager = requireActivity().getSystemService(
            NotificationManager::class.java
        )
        notificationManager.createNotificationChannel(notificationChannel)
    }
    // TODO: Step 1.6 END create channel
}
  1. Em seguida, para criar um canal, é preciso chamar a função createChannel() que você acabou de escrever (Etapa 1.7). Essa função usa dois parâmetros, o ID e o nome do canal. Você precisa procurar o ID e o nome do seu canal nos recursos de string que já estão fornecidos no projeto.
// EggTimerFragment.kt
    // TODO: Step 1.7 call createChannel
    createChannel(
          getString(R.string.egg_notification_channel_id),
          getString(R.string.egg_notification_channel_name)
    )
  1. Você precisa transmitir o ID do canal ao criador de notificações. Você já fez isso na Etapa 1.2. Definir um valor errado como ID do canal fará com que a notificação falhe. Abra NotificationUtils.kt para verificar se o ID do canal que você definiu anteriormente está correto.
// NotificationUtils.kt
val builder = NotificationCompat.Builder(
        applicationContext,
       // TODO: Step 1.8 verify the notification channel name
        applicationContext.getString(R.string.egg_notification_channel_id)
)
  1. Execute o app. Você verá uma notificação sempre que iniciar o timer.
  2. Puxe a barra de status e observe que o título, o conteúdo e o ícone da notificação são os mesmos que você definiu nas etapas anteriores.
  3. Para verificar o canal recém-criado, feche o app e encontre o ícone dele. Toque no ícone do app e o mantenha pressionado e selecione Informações do app.

  1. Selecione Notificações na lista de configurações. Você verá um novo canal chamado Egg abaixo da configuração Mostrar notificações.

Quando você executa o app, a notificação agora é exibida. Você como desenvolvedor de apps e seus usuários podem personalizar as configurações e o comportamento de todas as notificações enviadas neste canal. Parabéns, você criou uma notificação!

Etapa 3: adicionar notificações ao app

Até agora, isso mostra o uso básico da API de notificações, mas enviar uma notificação logo depois de iniciar o timer não faz muito sentido. Os usuários provavelmente preferem receber uma notificação quando o ovo estiver pronto. Na parte a seguir do codelab, você corrigirá isso e mudará a mensagem de aviso para uma notificação.

Você já enviou a notificação e observou como ela é exibida para os usuários, mas este é apenas o primeiro passo para criar notificações incríveis. Nesta etapa, você mudará a notificação para ser enviada no horário mais apropriado.

Seu app usa o AlarmManager para configurar um alarme. O código relacionado a AlarmManager já é fornecido no código inicial e usado para mostrar a mensagem de aviso. AlarmManager monitora a seleção de horário desejada e aciona a função onReceive() de AlarmReceiver.kt quando o tempo termina. Se você abrir o AlarmReceiver.kt e navegar para o onReceive(), verá a mensagem de aviso exibida sempre que configurar um timer de ovo.

  1. Abra AlarmReceiver.kt, uma instância de NotificationManager, e chame a função sendNotification() com o texto da mensagem e os parâmetros de contexto.
// AlarmReceiver.kt
   // TODO: Step 1.9 add call to sendNotification
   val notificationManager = ContextCompat.getSystemService(
       context, 
       NotificationManager::class.java
   ) as NotificationManager
             
   notificationManager.sendNotification(
       context.getText(R.string.eggs_ready).toString(), 
       context
   )
  1. Como alternativa, remova o aviso, já que o app enviará uma notificação quando o timer chegar ao fim.
// AlarmReceiver.kt
     // TODO: Step 1.10 [Optional] remove toast
//   Toast.makeText(
//       context, 
//       context.getText(R.string.eggs_ready),
//       Toast.LENGTH_SHORT
//   ).show()
  1. Execute o app . Você verá uma notificação sempre que iniciar o timer e sempre que ele acabar.

Isso não é o ideal. Você não quer enviar muitas notificações para seus usuários. Você pode remover a primeira notificação enviada quando o usuário inicia o timer.

  1. Abra EggTimerFragment.kt e remova o código da notificação da Etapa 1.5.
// EggTimeViewModel.kt

// TODO: Step 1.5 get an instance of NotificationManager 
// and call sendNotification
// val notificationManager = ContextCompat.getSystemService(
//      app,
//      NotificationManager::class.java
// ) as NotificationManager
// notificationManager.sendNotification(app.getString(R.string.eggs_ready), app)
  1. Execute o app novamente.
  2. Defina um timer, coloque-o em segundo plano e aguarde o tempo terminar. Você verá uma notificação. Essa é uma notificação muito mais útil.

Etapa 4: adicionar uma intent de conteúdo

  1. Execute o app novamente, caso ele ainda não esteja em execução.
  2. Clique na notificação. Nada acontecerá.

É ótimo mostrar a notificação e informar o usuário, mas quando ele clica em uma, ele volta para o app correspondente. Nesta parte do codelab, você adicionará uma intent à notificação para redirecioná-lo à tela do timer.

Um Intent é um objeto de mensagem que pode ser usado para solicitar uma ação de outro componente do app. Intents podem ser usadas para iniciar atividades, serviços ou transmissões. Nesse caso, você usa essa intent para instruir o sistema a abrir o app MainActivity quando o usuário tocar na notificação. Como seu app consiste em apenas uma visualização, não há muitas opções. No entanto, em um app maior, a notificação deve criar uma experiência perfeita, levando o usuário a uma tela que faz sentido quando ele interage com ela.

  1. Abra NotificationUtils.kt e localize a função de extensão sendNotification().
  2. Crie uma Intent com seu applicationContext e a atividade a ser iniciada, MainActivity::class.java.
// NotificationUtils.kt

fun NotificationManager.sendNotification(messageBody: String, applicationContext: Context) {
    // Create the content intent for the notification, which launches
    // this activity
   // TODO: Step 1.11 create intent
    val contentIntent = Intent(applicationContext, MainActivity::class.java)

Você criou a intent, mas a notificação é exibida fora do app. Para que uma intent funcione fora do app, crie uma nova PendingIntent.

PendingIntent concede direitos a outro aplicativo ou ao sistema para realizar uma operação em nome do seu app. Uma PendingIntent em si é simplesmente uma referência a um token mantido pelo sistema, descrevendo os dados originais usados para recuperá-los. Isso significa que, mesmo que o processo do aplicativo proprietário seja eliminado, o próprio PendingIntent permanecerá utilizável em relação a outros processos a que foi fornecido. Nesse caso, o sistema usará a intent pendente para abrir o app em seu nome, independentemente de ele estar ou não em execução.

  1. Crie um PendingIntent com applicationContext, NOTIFICATION_ID, o contentIntent que você criou na etapa anterior e a sinalização PendingIntent. A sinalização PendingIntent especifica a opção de criar um novo PendingIntent ou usar um existente. Você precisa definir PendingIntent.FLAG_UPDATE_CURRENT como a sinalização, porque não quer criar uma nova notificação se já houver uma. Dessa forma, você modificará o PendingIntent atual associado à intent que está fornecendo.
// NotificationUtils.kt
   // TODO: Step 1.12 create PendingIntent
    val contentPendingIntent = PendingIntent.getActivity(
        applicationContext, 
        NOTIFICATION_ID,
        contentIntent,
        PendingIntent.FLAG_UPDATE_CURRENT
    )
  1. Transmita o PendingIntent para sua notificação. Para fazer isso, chame setContentIntent() na NotificationBuilder. Agora, quando você clicar na notificação, o PendingIntent será acionado, abrindo seu MainActivity.
  2. Defina também setAutoCancel() como true, para que, quando o usuário tocar na notificação, ela seja dispensada enquanto a leve ao app.
// NotificationUtils.kt
    // TODO: Step 1.13 set content intent
    .setContentIntent(contentPendingIntent)
    .setAutoCancel(true)
  1. Execute o app novamente.
  2. Defina um timer, coloque o app em segundo plano e aguarde a notificação ser exibida.
  3. Depois de ver a notificação, clique nela para ver a barra de status e observe como o app é colocado em primeiro plano.

Etapa 5: cancelar a notificação

Você tem um timer de ovo funcional com notificações, mas há um pequeno problema. Se você definir o timer, receber uma notificação e defini-lo novamente, a notificação anterior permanecerá na barra de status enquanto o novo timer estiver em execução. Isso pode confundir o usuário se o app estiver em segundo plano e resultar em ovos mal cozidos.

Para corrigir isso, é necessário limpar a notificação anterior ao iniciar um novo timer. Para começar, crie outra função de extensão no NotificationUtils.kt. NotificationManager tem uma API para cancelar todas as notificações ativas chamadas cancelAll().

  1. Abra o NotificationsUtil.kt
  2. Adicione uma função de extensão em NotificationManager que chame cancelAll().
// NotificationUtils.kt

// TODO: Step 1.14 Cancel all notifications
/**
 * Cancels all notifications.
 *
 */
fun NotificationManager.cancelNotifications() {
    cancelAll()
}
  1. Abra EggTimerViewModel.kt e navegue até a função startTimer().
  2. No método startTimer(), acesse uma instância do NotificationManager do sistema e chame cancelNotifications().
//  EggTimerViewModel.kt
   //TODO Step 1.15 call cancel notification
    val notificationManager =
       ContextCompat.getSystemService(
            app,
            NotificationManager::class.java
        ) as NotificationManager
    notificationManager.cancelNotifications()       
  1. Execute o app e inicie o timer.
  2. Depois de ver a notificação, inicie o timer novamente e observe como nosso app exclui automaticamente a notificação anterior da barra de status.

O framework de notificações oferece várias opções de personalização para que os desenvolvedores definam ações personalizadas e estilizem as notificações conforme necessário. Nesta tarefa, você aprenderá a personalizar as notificações do timer do ovo.

Etapa 1: definir o estilo da notificação

A estilização da notificação de acordo com suas necessidades e o conteúdo dela fará com que as notificações se destaquem e se pareçam com uma extensão do seu aplicativo. O framework de notificação vem com vários estilos integrados para ajudar. Você também pode criar seus próprios estilos.

NotificationCompat oferece estilos integrados para:

  • BigTextStyle, que pode exibir um grande bloco de texto, como mostrar o conteúdo de um e-mail quando expandido.
  • BigPictureStyle, que mostra notificações em formato grande que incluem um anexo de imagem grande.
  • InboxStyle, que mostra um conteúdo de texto em estilo de conversa.
  • MediaStyle, que mostra controles para a reprodução de mídia.
  • MessagingStyle, que mostra notificações em formato grande que incluem várias mensagens entre diversas pessoas.

Veja mais informações sobre outros estilos na documentação Criar uma notificação expansível. Nesta etapa, você usará o NotificationCompat.BigPictureStyle para criar uma notificação expansível que mostra uma imagem de ovo grande quando expandida.

  1. Abra NotificationUtils.kt e localize a função sendNotification().
  2. Comece carregando uma imagem de resources usando a BitmapFactory.
// NotificationUtils.kt

// TODO: Step 2.0 add style
val eggImage = BitmapFactory.decodeResource(
     applicationContext.resources, 
     R.drawable.cooked_egg
)
  1. Crie uma nova BigPictureStyle e defina sua imagem.
  2. Defina o bigLargeIcon() como null para que o ícone grande desapareça quando a notificação for expandida.
// NotificationUtils.kt

// TODO: Step 2.0 add style
val eggImage = BitmapFactory.decodeResource(
     applicationContext.resources, 
     R.drawable.cooked_egg
)
val bigPicStyle = NotificationCompat.BigPictureStyle()
        .bigPicture(eggImage)
        .bigLargeIcon(null)
  1. Defina o estilo com setStyle() como bigPicStyle.
  2. Defina o ícone grande com setLargeIcon() como eggImage. Assim, a imagem será exibida como um ícone menor quando a notificação for recolhida.
// NotificationUtils.kt
// TODO: Step 2.1 add style to builder
.setStyle(bigPicStyle)
.setLargeIcon(eggImage)
  1. Execute o app e defina um timer. Quando a notificação é mostrada pela primeira vez, ela está no estado recolhido na gaveta de notificações. Se você expandir a notificação, uma imagem grande será exibida na área de notificação estendida.

Etapa 2: ações da notificação

As ações de notificação são outra personalização que pode ser adicionada às suas notificações. No momento, as notificações são redirecionadas para seu app quando os usuários clicam nelas. Além dessa ação padrão de notificação, é possível adicionar botões de ação que concluam uma tarefa relacionada ao app a partir da notificaçã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. Esses botões não podem duplicar a ação realizada quando o usuário toca na notificação.

Para adicionar um botão de ação, transmita um PendingIntent para a função addAction() no builder. Isso é semelhante a configurar a ação de toque padrão da notificação chamando setContentIntent(). A diferença é que, em vez de iniciar uma atividade, você pode fazer várias outras ações, por exemplo, iniciar um BroadcastReceiver que execute um job em segundo plano para que a ação não interrompa o app que já está aberto.

Neste codelab, você já recebeu um BoadcastReceiver chamado SnoozeReceiver. Você usará o SnoozeReceiver para receber o clique do usuário na ação de notificação. Nas etapas a seguir, você adicionará um código para adiar a notificação do timer de ovo por 60 segundos quando o usuário clicar no botão de soneca. Quando a ação de soneca for clicada, o SnoozeReceiver receberá uma intent e criará um novo alarme para enviar uma nova notificação após 60 segundos.

  1. Abra o SnoozeReceiver.kt Essa classe é semelhante à AlarmReceiver que você usou anteriormente. Nas etapas a seguir, você adicionará um código que acionará a função onReceive() do SnoozeReceiver. Em resumo, o código em SnoozeReceiver criará um novo alarme para enviar uma nova notificação um minuto depois. Role a tela até a parte inferior da função onReceive, receba uma instância de notificationManager do sistema e chame cancelAll.
// SnoozeReceiver.kt
        val notificationManager = ContextCompat.getSystemService(
            context,
            NotificationManager::class.java
        ) as NotificationManager
        notificationManager.cancelAll()
  1. Para usar SnoozeReceiver, abra NotificationUtils.kt.
  2. Crie um novo Intent snoozeIntent para a SnoozeReceiver logo após o estilo na função sendNotification().
  3. Crie uma intent pendente chamando o método getBroadcast() na PendingIntent, que espera os parâmetros nas etapas a seguir. Este PendingIntent será usado pelo sistema para configurar um novo alarme para postar uma nova notificação após 60 segundos quando o botão de soneca for tocado pelo usuário.
  4. O primeiro parâmetro é o contexto do aplicativo em que o PendingIntent precisa iniciar a atividade.
  5. O segundo parâmetro é o código da solicitação da intent pendente. Se você precisar atualizar ou cancelar essa intent pendente, será necessário usar este código para acessá-la.
  6. Em seguida, adicione o objeto snoozeIntent, que é a intent da atividade que será iniciada.
  7. Por fim, adicione o valor da sinalização #FLAG_ONE_SHOT, porque a intent será usada apenas uma vez. A ação rápida e a notificação desaparecerão após o primeiro toque. É por isso que a intent só pode ser usada uma vez.
// NotificationUtils.kt

// TODO: Step 2.2 add snooze action
val snoozeIntent = Intent(applicationContext, SnoozeReceiver::class.java)
val snoozePendingIntent: PendingIntent = PendingIntent.getBroadcast(
    applicationContext, 
    REQUEST_CODE, 
    snoozeIntent, 
    FLAGS
)
  1. Em seguida, chame a função addAction() no notificationBuilder. Essa função precisa de um ícone e um texto para descrever a ação para o usuário. Você também precisa adicionar o snoozeIntent. Essa intent será usada para acionar o boadcastReceiver correto quando sua ação receber um clique.
// NotificationUtils.kt
// TODO: Step 2.3 add snooze action
.addAction(
    R.drawable.egg_icon, 
    applicationContext.getString(R.string.snooze),
    snoozePendingIntent
)
  1. Execute o app timer do ovo para testar a ação de soneca.
  2. Execute o timer e coloque o app em segundo plano. Quando o timer acabar, expanda a notificação para mostrar que o botão de soneca está suspenso por mais um minuto.

Etapa 3: importância das notificações

A importância determina o quanto a notificação deve interromper o usuário visual e audível. As notificações com maior importância serão mais interruptivas para os usuários.

Especifique o nível de importância no construtor do NotificationChannel. Originalmente, você definiu uma importância baixa para o app de timer do ovo. É possível usar um dos cinco níveis de importância, variando de IMPORTANCE_NONE(0) a IMPORTANCE_HIGH(4). O nível de importância atribuído a um canal se aplica a todas as mensagens de notificação que você posta nele.

Níveis de importância do canal

Nível de importância visível para o usuário

Importância (Android 8.0 e versões mais recentes)

Prioridade (Android 7.1 e versões anteriores)

Emite um som e aparece como uma notificação de informações básicas (exibida na parte superior da tela).

IMPORTANCE_HIGH

PRIORITY_HIGH / PRIORITY_MAX

Emite um som

IMPORTANCE_DEFAULT

PRIORITY_PADRÃO

Sem som

IMPORTANCE_LOW (em inglês)

PRIORITY_LOW;

Não emite som e não aparece na barra de status

IMPORTANCE_MIN (em inglês)

PRIORITY_MIN (em inglês)

Para mais informações sobre como escolher um nível adequado de prioridade, consulte "Índices de prioridade" no guia de design para notificações. Tenha cuidado ao selecionar um nível de importância para as notificações no seu app. A importância do canal precisa ser escolhida considerando o tempo e a atenção do usuário. Quando uma notificação sem importância é disfarçada como urgente, ela pode produzir um alarme desnecessário e causar distração. Os usuários têm controle total sobre a importância das notificações. Portanto, se você criar uma notificação irritante, ele poderá desativar completamente seu canal de notificações.

Quando você criou a notificação na Etapa 1.6, o timer do ovo foi definido para enviar notificações com baixa prioridade, já que ele foi projetado para não incomodar o usuário com notificações. No entanto, talvez seja uma boa ideia chamar a atenção do usuário antes do cozimento do ovo. Para mudar o nível de importância da notificação, acesse as configurações do canal. A importância do canal afeta o nível de interrupção de todas as notificações postadas no canal, e precisa ser especificada no construtor NotificationChannel.

  1. Para mudar o nível de importância do canal de notificações do app, abra EggTimerFragment.kt e navegue até createChannel(). Mude o nível de importância de IMPORTANCE_LOW para IMPORTANCE_HIGH.
// EggTimerFragment.kt
    val notificationChannel = NotificationChannel(
        channelId,
        channelName,
        // TODO: Step 2.4 change importance
        NotificationManager.IMPORTANCE_HIGH
    )

Para oferecer compatibilidade com dispositivos com o Android 7.1 (nível 25 da API) ou versões anteriores, você também precisa chamar setPriority() para cada notificação usando uma constante de prioridade da classe NotificationCompat.

  1. Abra NotificationUtils.kt e adicione o código a seguir ao objeto do builder de notificações.
// NotificationUtils.kt
   .addAction(
       R.drawable.common_google_signin_btn_icon_dark,
       applicationContext.getString(R.string.snooze),
       snoozePendingIntent
    )
   // TODO: Step 2.5 set priority
    .setPriority(NotificationCompat.PRIORITY_HIGH)
  1. Antes de executar o app, clique e mantenha pressionado o ícone dele no dispositivo ou emulador e selecione "Desinstalar" para limpar as configurações anteriores do canal. Se você não desinstalar o app, as configurações de prioridade do canal não serão alteradas, e isso não resultará em nenhuma mudança de comportamento quando a notificação for postada.
  2. Execute o app novamente e inicie o timer. Desta vez, quando a notificação for enviada, você verá um pop-up na parte superior da tela, independente do app estar sendo executado em primeiro ou segundo plano.

Etapa 4: selos de notificação

Os selos de notificação são pequenos pontos que aparecem no ícone na tela de início do app associado quando o app tem uma notificação ativa. Os usuários podem tocar no ícone do app e mantê-lo pressionado para ver as notificações.

Esses pontos, chamados de selos, são exibidos por padrão e não há nada que seu app precise fazer. No entanto, pode haver situações em que os selos não façam sentido para suas notificações, portanto, você pode desativá-los por canal chamando setShowBadge(false) no seu objeto NotificationChannel. Como o timer do ovo tem apenas uma notificação ativa por vez, o ícone no ícone do app não oferece muito benefícios aos usuários. Nas etapas a seguir, você desativará o ícone e mostrará uma notificação apenas para o timer de ovo.

  1. Adicione setShowBadge(false) ao código de criação do canal para que o timer de ovo desative os selos.
// EggTimerFragment.kt

    ).apply {
        // TODO: Step 2.6 disable badges for this channel
        setShowBadge(false)
    }
  1. Execute o app novamente, inicie o timer e veja o ícone dele. Você não verá nenhum ícone no ícone do app.

O código da solução está na ramificação mestre do código transferido por download.

Curso da Udacity:

Documentação do desenvolvedor Android:

Para ver links de outros codelabs neste curso, consulte a página de destino dos codelabs avançados no Android.