Os dispositivos Wear OS são usados com frequência para experiências de longa duração, como o rastreamento de um treino. Isso apresenta um desafio para a experiência do usuário: se um usuário iniciar uma tarefa e depois navegar até o mostrador do relógio, como ele volta? Voltar ao app usando o iniciador pode ser difícil, especialmente quando você está em movimento, criando atrito desnecessário.
A solução é parear uma notificação em andamento com um OngoingActivity
.
Isso permite que o dispositivo mostre informações sobre a atividade de longa duração
na interface do usuário, ativando recursos como o ícone de toque na
parte de baixo do mostrador do relógio. Isso mantém os usuários cientes da tarefa em segundo plano e
oferece uma maneira de voltar ao app com um toque.
Por exemplo, neste app de treino, as informações podem aparecer no mostrador do relógio do usuário como um ícone de corrida que pode ser tocado:
Figura 1. Indicador de atividade
Uma notificação em andamento também mostra informações na seção Recentes do Acesso rápido aos apps global. Assim, os usuários têm outro lugar conveniente para conferir o status da tarefa e voltar a interagir com o app:
Figura 2. Acesso rápido global
Confira abaixo boas situações para usar uma notificação em andamento vinculada a uma atividade em andamento:
Figura 3. Cronômetro:faz a contagem ativa de tempo decorrido e termina quando o cronômetro é pausado/interrompido.
Figura 4. Navegação guiada:mostra rotas para um destino. Termina quando o usuário chega ao destino ou para a navegação.
Figura 5. Mídia:reproduz música durante uma sessão. Termina imediatamente após o usuário pausar a sessão.
O Wear cria atividades em andamento automaticamente para apps de música.
Consulte o codelab sobre Atividades em andamento para um exemplo detalhado da criação dessas atividades para outros tipos de apps.
Configuração
Para começar a usar a API Ongoing Activity no app, adicione as
dependências abaixo ao arquivo build.gradle
do app:
dependencies {
implementation "androidx.wear:wear-ongoing:1.1.0"
implementation "androidx.core:core:1.17.0"
}
Criar uma atividade em andamento
O processo envolve três etapas:
- Crie um
NotificationCompat.Builder
padrão e configure-o como contínuo. - Crie e configure um objeto
OngoingActivity
, transmitindo o criador de notificações para ele. - Aplique a atividade em andamento ao builder de notificações e poste a notificação resultante.
Criar e configurar a notificação
Comece criando um NotificationCompat.Builder
. A etapa principal é chamar
setOngoing(true)
para marcá-la como uma notificação em andamento. Você também pode definir outras propriedades de notificação nessa etapa, como o ícone pequeno e a categoria.
// Create a PendingIntent to pass to the notification builder val pendingIntent = PendingIntent.getActivity( this, 0, Intent(this, AlwaysOnActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_SINGLE_TOP }, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE, ) val notificationBuilder = NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle("Always On Service") .setContentText("Service is running in background") .setSmallIcon(R.drawable.animated_walk) // Category helps the system prioritize the ongoing activity .setCategory(NotificationCompat.CATEGORY_WORKOUT) .setContentIntent(pendingIntent) .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) .setOngoing(true) // Important!
Criar o OngoingActivity
Em seguida, crie uma instância de OngoingActivity
usando o builder correspondente. O
OngoingActivity.Builder
exige um Context
, um ID de notificação e o
NotificationCompat.Builder
criado na etapa anterior.
Configure as propriedades principais que serão mostradas nas novas plataformas de interface:
- Ícones animados e estáticos: forneça ícones que são exibidos no mostrador do relógio nos modos ativo e ambiente.
- Intent de toque: uma
PendingIntent
que traz o usuário de volta ao seu app quando ele toca no ícone de atividade em andamento. Você pode reutilizar opendingIndent
criado na etapa anterior.
val ongoingActivity = OngoingActivity.Builder(applicationContext, NOTIFICATION_ID, notificationBuilder) // Sets the icon that appears on the watch face in active mode. .setAnimatedIcon(R.drawable.animated_walk) // Sets the icon that appears on the watch face in ambient mode. .setStaticIcon(R.drawable.ic_walk) // Sets the tap target to bring the user back to the app. .setTouchIntent(pendingIntent) .build()
Aplicar à notificação e postar
A etapa final é vincular o OngoingActivity
à notificação e postar. O método ongoingActivity.apply()
modifica o criador de notificações original, adicionando os dados necessários para que o sistema possa mostrar a notificação nas outras plataformas. Depois de aplicar, crie e publique a notificação
como de costume.
// This call modifies notificationBuilder to include the ongoing activity data. ongoingActivity.apply(applicationContext) // Post the notification. startForeground(NOTIFICATION_ID, notificationBuilder.build())
Adicionar texto de status dinâmico à tela de início
O código anterior adiciona o ícone tocável ao mostrador do relógio. Para oferecer atualizações ainda
mais completas e em tempo real na seção Recentes da tela de início, crie um
objeto Status
e anexe-o ao seu OngoingActivity
. Se você não fornecer um Status
personalizado, o sistema usará o texto do conteúdo da notificação (definido com setContentText()
).
Para mostrar texto dinâmico, use um Status.Builder
. É possível definir uma string de modelo com marcadores de posição e fornecer objetos Status.Part
para preencher esses marcadores. O Status.Part
pode ser dinâmico, como um cronômetro ou timer .
O exemplo a seguir mostra como criar um status que exibe "Executar por [um cronômetro]":
// Define a template with placeholders for the activity type and the timer. val statusTemplate = "#type# for #time#" // Set the start time for a stopwatch. // Use SystemClock.elapsedRealtime() for time-based parts. val runStartTime = SystemClock.elapsedRealtime() val ongoingActivityStatus = Status.Builder() // Sets the template string. .addTemplate(statusTemplate) // Fills the #type# placeholder with a static text part. .addPart("type", Status.TextPart("Run")) // Fills the #time# placeholder with a stopwatch part. .addPart("time", Status.StopwatchPart(runStartTime)) .build()
Por fim, vincule essa Status
ao OngoingActivity
chamando setStatus()
no OngoingActivity.Builder
.
val ongoingActivity = OngoingActivity.Builder(applicationContext, NOTIFICATION_ID, notificationBuilder) // ... // Add the status to the OngoingActivity. .setStatus(ongoingActivityStatus) .build()
Outras personalizações
Além de Status
, você pode personalizar as atividades ou notificações em andamento das
seguintes formas. No entanto, essas personalizações podem não ser usadas, com base na
implementação do OEM.
Notificação em andamento
- A categoria definida determina a prioridade da atividade em andamento.
CATEGORY_CALL
:uma ligação ou videochamada recebida ou uma solicitação de comunicação síncrona semelhanteCATEGORY_NAVIGATION
: um mapa ou uma navegação guiadaCATEGORY_TRANSPORT
: controle de transporte de mídia para reproduçãoCATEGORY_ALARM
: um alarme ou timerCATEGORY_WORKOUT
:um treinoCATEGORY_LOCATION_SHARING
:compartilhamento temporário de local categoria)CATEGORY_STOPWATCH
:cronômetro
Atividade em andamento
Ícone animado: um vetor em preto e branco, de preferência com um segundo plano transparente. Aparece no mostrador do relógio no modo ativo. Se o ícone animado não for fornecido, o ícone de notificação padrão será usado. O ícone de notificação padrão é diferente para cada aplicativo.
Ícone estático: ícone vetorial com segundo plano transparente. Aparece no mostrador do relógio no modo ambiente. Se o ícone animado não estiver definido, o ícone estático vai ser usado no mostrador do relógio no modo ativo. Se esse valor não for fornecido, o ícone de notificação vai ser usado. Se nenhuma delas for definida, uma exceção vai ser gerada. A tela de início ainda vai usar o ícone do app.
OngoingActivityStatus: texto simples ou um
Chronometer
. Aparece na seção Recentes da tela de início. Se não for informado, vai ser usada a notificação "texto de contexto".Intent de toque: uma
PendingIntent
usada para voltar ao app se o usuário tocar no ícone de atividade em andamento. Aparece no mostrador do relógio ou no item da tela de início. Pode ser diferente da intent original usada para iniciar o app. Se não for fornecida, a intent de conteúdo da notificação será usada. Se nenhuma delas for definida, uma exceção será gerada.LocusId
:um ID que atribui o atalho da tela de início a que a atividade em andamento corresponde. Aparece na tela de início na seção Recentes enquanto a atividade está em andamento. Se não for fornecido, a tela de início vai ocultar todos os itens do app na seção Recentes do mesmo pacote e mostrar apenas a atividade em andamento.ID de atividade em andamento:um ID usado para diferenciar as chamadas para
fromExistingOngoingActivity()
quando um aplicativo tem mais de uma atividade em andamento.
Atualizar uma atividade em andamento
Na maioria dos casos, os desenvolvedores criam uma nova notificação e uma nova atividade
em andamento quando precisam atualizar os dados na tela. No entanto, a API Ongoing
Activity também oferece métodos auxiliares para atualizar um OngoingActivity
se você
quiser reter uma instância em vez de recriá-la.
Se o app estiver em execução em segundo plano, ele vai poder enviar atualizações para a API Ongoing Activity. No entanto, não faça isso com muita frequência, porque o método de atualização ignora chamadas muito próximas umas das outras. Algumas atualizações por minuto são razoáveis.
Para atualizar a atividade em andamento e a notificação postada, use o objeto
criado anteriormente e chame update()
, conforme mostrado no exemplo abaixo:
ongoingActivity.update(context, newStatus)
Por conveniência, há um método estático para criar uma atividade em andamento.
OngoingActivity.recoverOngoingActivity(context)
.update(context, newStatus)
Interromper uma atividade em andamento
Quando o app termina de ser executado como uma atividade em andamento, ele só precisa cancelar a notificação em andamento.
Também é possível cancelar a notificação ou a atividade em andamento quando ela está em primeiro plano e, depois, recriá-la quando voltar ao segundo plano, mas isso não é necessário.
Pausar uma atividade em andamento
Se o app tiver uma ação de interrupção explícita, continue a atividade em andamento depois que ela for retomada. Para um app sem uma ação de parada explícita, encerre a atividade quando ela estiver pausada.
Práticas recomendadas
Não esqueça dos princípios abaixo ao trabalhar com a API Ongoing Activity:
Defina um ícone estático para a atividade em andamento, explicitamente ou como um substituto usando a notificação. Caso contrário, uma
IllegalArgumentException
vai ser gerada.Use ícones vetoriais pretos e brancos com planos de fundo transparentes.
Defina uma intent de toque para a atividade em andamento, explicitamente ou como um substituto usando a notificação. Caso contrário, uma
IllegalArgumentException
vai ser gerada.Se o app tiver mais de uma atividade
MAIN LAUNCHER
declarada no manifesto, publique um atalho dinâmico e associe-o à atividade em andamento usandoLocusId
.
Publicar notificações ao abrir mídia em dispositivos Wear OS
Se estiver tocando conteúdo de mídia em um dispositivo Wear OS, publique uma notificação de mídia. Isso permite que o sistema crie uma atividade em andamento correspondente.
Se você estiver usando a Media3, a notificação será publicada automaticamente. Se você
criar sua notificação manualmente, ela vai usar o
MediaStyleNotificationHelper.MediaStyle
, e a
MediaSession
correspondente terá a atividade da sessão preenchida.
Recomendados para você
- Observação: o texto do link aparece quando o JavaScript está desativado.
- Criar uma notificação {:#notification}
- Usar a API Ongoing Activity para engajar os usuários do Wear OS de novas maneiras
- Criar uma notificação expansível {:#expandable-notification}