Use balões para permitir que os usuários participem de conversas

Os balões permitem que os usuários vejam e participem das conversas com mais facilidade.

Figura 1. Um balão de chat.

Os balões são integrados ao sistema de notificação. Eles flutuam sobre o conteúdo de outros apps e seguem o usuário em qualquer lugar. Os usuários podem expandir os balões para revelar a funcionalidade e as informações do app e podem recolhê-los quando não estiverem em uso.

Quando o dispositivo está bloqueado ou a tela sempre ativada está ativa, os balões aparecem, assim como as notificações normalmente.

Os balões são um recurso que pode ser desativado. Quando um app apresenta o primeiro balão, uma caixa de diálogo de permissões oferece duas opções:

  • Bloquear todos os balões do app. As notificações não são bloqueadas, mas nunca aparecem como balões.
  • Permitir todos os balões do app. Todas as notificações enviadas com BubbleMetaData aparecem como balões.

A API da bolha

Os balões são criados por meio da API de notificação. Portanto, envie a notificação normalmente. Se você quiser que a notificação seja exibida como um balão, anexe dados extras a ela.

A exibição expandida de uma bolha é criada a partir de uma atividade escolhida por você. Configure a atividade para que ela seja exibida corretamente como um balão. A atividade precisa ser redimensionável e incorporada. Se algum desses requisitos não for atendido, ela será exibida como uma notificação.

O código a seguir demonstra como implementar uma bolha simples:

<activity
  android:name=".bubbles.BubbleActivity"
  android:theme="@style/AppTheme.NoActionBar"
  android:label="@string/title_activity_bubble"
  android:allowEmbedded="true"
  android:resizeableActivity="true"
/>

Se o app mostra vários balões do mesmo tipo, como várias conversas de chat com diferentes contatos, a atividade precisa conseguir iniciar várias instâncias. Em dispositivos com o Android 10 e versões anteriores, as notificações não são exibidas como balões, a menos que você defina explicitamente documentLaunchMode como "always". No Android 11 e versões mais recentes, não é necessário definir explicitamente esse valor, porque o sistema define automaticamente todas as conversas de documentLaunchMode como "always".

Para enviar uma bolha, siga estas etapas:

  1. Crie uma notificação normalmente.
  2. Chame BubbleMetadata.Builder(PendingIntent, Icon) ou BubbleMetadata.Builder(String) para criar um objeto BubbleMetadata.
  3. Use setBubbleMetadata() para adicionar os metadados à notificação.
  4. Se o app for destinado ao Android 11 ou versões mais recentes, verifique se os metadados ou a notificação do balão fazem referência a um atalho de compartilhamento.

Essas etapas são mostradas no exemplo a seguir:

Kotlin

// Create a bubble intent.
val target = Intent(context, BubbleActivity::class.java)
val bubbleIntent = PendingIntent.getActivity(context, 0, target, 0 /* flags */)
val category = "com.example.category.IMG_SHARE_TARGET"

val chatPartner = Person.Builder()
    .setName("Chat partner")
    .setImportant(true)
    .build()

// Create a sharing shortcut.
val shortcutId = generateShortcutId()
val shortcut =
   ShortcutInfo.Builder(mContext, shortcutId)
       .setCategories(setOf(category))
       .setIntent(Intent(Intent.ACTION_DEFAULT))
       .setLongLived(true)
       .setShortLabel(chatPartner.name)
       .build()

// Create a bubble metadata.
val bubbleData = Notification.BubbleMetadata.Builder(bubbleIntent,
            Icon.createWithResource(context, R.drawable.icon))
    .setDesiredHeight(600)
    .build()

// Create a notification, referencing the sharing shortcut.
val builder = Notification.Builder(context, CHANNEL_ID)
    .setContentIntent(contentIntent)
    .setSmallIcon(smallIcon)
    .setBubbleMetadata(bubbleData)
    .setShortcutId(shortcutId)
    .addPerson(chatPartner)

Java

// Create a bubble intent.
Intent target = new Intent(mContext, BubbleActivity.class);
PendingIntent bubbleIntent =
    PendingIntent.getActivity(mContext, 0, target, 0 /* flags */);

private val CATEGORY_TEXT_SHARE_TARGET =
    "com.example.category.IMG_SHARE_TARGET"

Person chatPartner = new Person.Builder()
        .setName("Chat partner")
        .setImportant(true)
        .build();

// Create a sharing shortcut.
private String shortcutId = generateShortcutId();
ShortcutInfo shortcut =
   new ShortcutInfo.Builder(mContext, shortcutId)
       .setCategories(Collections.singleton(CATEGORY_TEXT_SHARE_TARGET))
       .setIntent(Intent(Intent.ACTION_DEFAULT))
       .setLongLived(true)
       .setShortLabel(chatPartner.getName())
       .build();

// Create a bubble metadata.
Notification.BubbleMetadata bubbleData =
    new Notification.BubbleMetadata.Builder(bubbleIntent,
            Icon.createWithResource(context, R.drawable.icon))
        .setDesiredHeight(600)
        .build();

// Create a notification, referencing the sharing shortcut.
Notification.Builder builder =
    new Notification.Builder(mContext, CHANNEL_ID)
        .setContentIntent(contentIntent)
        .setSmallIcon(smallIcon)
        .setBubbleMetadata(bubbleData)
        .setShortcutId(shortcutId)
        .addPerson(chatPartner);

Se o app estiver em primeiro plano quando um balão for enviado, a importância será ignorada, e o balão será sempre exibido, a menos que o usuário bloqueie balões ou notificações do app.

Criar um balão expandido

Você pode configurar sua bolha para que ela seja automaticamente exibida no estado expandido. Recomendamos usar essa funcionalidade apenas se o usuário realizar uma ação que resulta em uma bolha, como tocar em um botão para iniciar um novo chat. Nesse caso, também faz sentido suprimir a notificação inicial enviada quando uma bolha é criada.

Existem métodos que podem ser usados para definir sinalizações que ativam esses comportamentos: setAutoExpandBubble() e setSuppressNotification().

O exemplo a seguir mostra como configurar um balão para apresentar automaticamente em um estado expandido:

Kotlin

val bubbleMetadata = Notification.BubbleMetadata.Builder()
    .setDesiredHeight(600)
    .setIntent(bubbleIntent)
    .setAutoExpandBubble(true)
    .setSuppressNotification(true)
    .build()

Java

Notification.BubbleMetadata bubbleData =
    new Notification.BubbleMetadata.Builder()
        .setDesiredHeight(600)
        .setIntent(bubbleIntent)
        .setAutoExpandBubble(true)
        .setSuppressNotification(true)
        .build();

Ciclo de vida do conteúdo do balão

Quando uma bolha é expandida, a atividade de conteúdo passa pelo ciclo de vida do processo normal, resultando em um processo em primeiro plano, caso isso ainda não tenha sido feito.

Quando o balão é recolhido ou dispensado, a atividade é destruída. Isso pode fazer com que o processo seja armazenado em cache e depois encerrado, dependendo se o app tem outros componentes em execução em primeiro plano.

Quando os balões aparecem

Para reduzir interrupções para o usuário, as bolhas só aparecem em determinadas circunstâncias.

Se um app for direcionado ao Android 11 ou a versões mais recentes, uma notificação não aparecerá como um balão, a menos que atenda aos requisitos da conversa. Se um app for direcionado ao Android 10 ou versões anteriores, a notificação só vai aparecer como um balão se uma ou mais das seguintes condições forem atendidas:

Se nenhuma dessas condições for atendida, a notificação será mostrada em vez de um balão.

Práticas recomendadas

  • Só envie uma notificação como um balão se ela for importante. Por exemplo, quando ela faz parte de uma comunicação contínua ou se o usuário solicita explicitamente um balão de conteúdo. Os balões usam o espaço da tela e cobrem o conteúdo de outros aplicativos.
  • Verifique se a notificação em balão também funciona como uma notificação normal. Quando o usuário desativar o balão, uma notificação em balão será exibida como uma notificação normal.
  • Mantenha a funcionalidade o mais específica e leve possível. Os processos iniciados em uma bolha, como atividades e caixas de diálogo, aparecem dentro do contêiner do balão. Isso significa que um balão pode ter uma pilha de tarefas. Os processos poderão se complicar se houver muitas funcionalidades ou navegação dentro do balão.
  • Chame super.onBackPressed ao substituir onBackPressed na atividade de balão. Caso contrário, o balão pode não se comportar corretamente.

Quando um balão recolhido recebe uma mensagem atualizada, ele mostra um ícone de selo para indicar uma mensagem não lida. Quando o usuário abrir a mensagem no app associado, siga estas etapas:

App de exemplo

O app de exemplo People é um app de conversa simples que usa balões. Para fins de demonstração, este app usa bots de chat. Em aplicativos reais, as bolhas só podem ser usadas para mensagens enviadas por humanos, e não por bots.