# Live Updates no Android

A Pushwoosh oferece suporte a Live Updates do Android através do módulo `pushwoosh-liveupdates` (SDK 6.9.0 e posterior). Um Live Update é uma notificação contínua, no estilo de progresso, que o sistema promove na tela de bloqueio, na gaveta de notificações e como um chip de status na barra de status, para que os usuários possam acompanhar uma atividade sem abrir seu aplicativo.

Todo o ciclo de vida é controlado pelo servidor: seu backend envia um push quando a atividade começa, mais pushes à medida que ela progride e um push final quando termina. O SDK renderiza cada um automaticamente.

## O que são Live Updates

Os Live Updates foram introduzidos no Android 16 (API 36) como uma forma de destacar uma atividade iniciada pelo usuário e sensível ao tempo, do início ao fim. Eles se baseiam nas notificações centradas em progresso da plataforma e na API `Notification.ProgressStyle`. Conceitualmente, eles são a contraparte Android das Live Activities do iOS.

Esta página aborda apenas a integração com a Pushwoosh. Para o comportamento da plataforma, regras de promoção e orientações de design, consulte a documentação oficial do Android:

- [Notificações centradas em progresso](https://developer.android.com/about/versions/16/features/progress-centric-notifications)
- [Criar notificações de atualização ao vivo (Views)](https://developer.android.com/develop/ui/views/notifications/live-update)
- [Criar notificações de atualização ao vivo (Compose)](https://developer.android.com/develop/ui/compose/notifications/live-update)

## Quando usar Live Updates

Os Live Updates são destinados a uma atividade que está em andamento, foi iniciada pelo usuário e é sensível ao tempo — algo com um início e fim claros com os quais o usuário se importa ativamente no momento. Cenários típicos para clientes da Pushwoosh:

- **Entrega de comida** — pedido aceito, em preparação, saiu para entrega, chegando.
- **Solicitação de caronas e táxi** — motorista atribuído, a caminho, chegando, viagem em andamento.
- **Rastreamento de pedidos e remessas** — status ao vivo de um pedido que está ativamente em trânsito.
- **Esportes e mídia ao vivo** — placar e tempo da partida conforme o jogo se desenrola.
- **Fitness** — um treino ou corrida ativa com tempo decorrido e progresso.
- **Fintech** — um fluxo de transação ou verificação passando por suas etapas.

Como o ciclo de vida é impulsionado por eventos reais que seu backend já conhece (um pedido muda de status, um entregador se move), um Live Update geralmente é uma chamada de API conectada ao seu fluxo de eventos existente — não algo que uma pessoa envia manualmente.

<Aside type="caution">
Não use Live Updates para promoções, mensagens de chat ou informações ambientais, e nunca reposte um Live Update que o usuário dispensou. O Android pode revogar a capacidade do aplicativo de postar notificações promovidas. Siga as [orientações do Android sobre o uso apropriado](https://developer.android.com/develop/ui/views/notifications/live-update#best-practices).
</Aside>

## Requisitos

- Android 16 (API 36) ou mais recente. Em dispositivos mais antigos, o módulo permanece inativo e cada chamada de API de Live Update é uma operação nula (no-op) segura.
- Pushwoosh Android SDK 6.9.0 ou posterior.

## Adicione o módulo pushwoosh-liveupdates

Adicione a dependência ao seu **app/build.gradle**:

```groovy
dependencies {
    implementation 'com.pushwoosh:pushwoosh-liveupdates:<latest-version>'
}
```

Substitua `<latest-version>` pela versão atual do [Maven Central](https://mvnrepository.com/artifact/com.pushwoosh/pushwoosh-liveupdates).

O módulo é descoberto automaticamente na inicialização. Ele declara a permissão `POST_PROMOTED_NOTIFICATIONS` necessária, registra seu próprio canal de notificação e intercepta os pushes de Live Update antes do caminho de notificação padrão. Não há código de inicialização extra — o SDK define os sinalizadores de andamento e promovido, baixa o ícone grande, mapeia os botões de ação e posta a notificação para você.

## Enviar um Live Update

Você envia Live Updates através da [API de Mensagens v2](/pt/developer/api-reference/messaging-api-v2/) adicionando um objeto `live_update` ao bloco de conteúdo `android`. Use uma solicitação `transactional` — um Live Update tem como alvo o usuário específico cuja atividade ele rastreia. O campo `schedule` é obrigatório; `{ "after": "0s" }` envia imediatamente. O ciclo de vida tem três operações, definidas em `live_update.op`:

- `OPERATION_START` — primeiro push para uma atividade. Posta a notificação em andamento.
- `OPERATION_UPDATE` — um push posterior para a mesma atividade. Atualiza-a no local, silenciosamente.
- `OPERATION_END` — push terminal. Dispensa a notificação.

Todos os pushes que pertencem à mesma atividade devem compartilhar o mesmo `live_update.id`. Esse id une as atualizações e também é o que você usa para dispensar a atualização a partir do aplicativo.

Cada push descreve completamente a notificação — nada é herdado do push anterior. Reenvie todos os campos que deseja manter, como os segmentos e o ícone grande, a cada `OPERATION_UPDATE`; um campo omitido é renderizado como ausente.

### Parâmetros de Live Update

Essas chaves vão dentro do objeto `live_update` do bloco de conteúdo `android`. Título, corpo e ícone grande usam os campos de push padrão do Android (`title`, `body`, `custom_icon`), enviados junto com `live_update`.

| Parâmetro | Tipo | Descrição |
|---|---|---|
| `op` | string | Operação do ciclo de vida: `OPERATION_START`, `OPERATION_UPDATE` ou `OPERATION_END`. Obrigatório. |
| `id` | string | ID de atividade estável compartilhado por todos os pushes de um Live Update. Obrigatório. |
| `progress` | int | Valor do progresso, medido em relação à soma dos comprimentos dos segmentos. |
| `progress_indeterminate` | bool | Mostra uma animação indeterminada em vez de um valor concreto. |
| `progress_bar` | bool | Mostra a barra de progresso. O padrão é `true`. |
| `segments` | array | Segmentos de progresso ordenados, cada um `{ "color": "#RRGGBB", "length": N }`. |
| `extras` | object | Dados arbitrários passados para um provedor de estilo personalizado. |
| `when` | int64 | Âncora de tempo do cabeçalho, em milissegundos da época (epoch). |
| `chronometer` | bool | Mostra o tempo do cabeçalho como um cronômetro em execução. |
| `chronometer_count_down` | bool | Um cronômetro em execução faz contagem regressiva em vez de progressiva. |
| `show_when` | bool | Mostra a coluna de tempo do cabeçalho. O padrão é `true`. |

<Aside>
O valor de `op` deve ser um dos nomes exatos do enum `OPERATION_START`, `OPERATION_UPDATE` ou `OPERATION_END` — formas abreviadas são ignoradas. Cada campo carrega seu tipo JSON nativo: `segments` é um array JSON e `extras` um objeto JSON, não strings codificadas.
</Aside>

Os quatro campos de tempo combinam-se da seguinte forma: com `show_when` definido como `false`, o tempo fica oculto; caso contrário, `when` é a âncora, `chronometer` o transforma em um contador ao vivo, e `chronometer_count_down` faz esse contador funcionar para trás.

### Push de início

```bash
curl -X POST https://api.pushwoosh.com/messaging/v2/notify \
  -H "Authorization: Token YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "transactional": {
      "application": "XXXXX-XXXXX",
      "platforms": ["ANDROID"],
      "users": { "list": ["customer-42"] },
      "payload": {
        "content": {
          "localized_content": {
            "default": {
              "android": {
                "title": "Order #4521",
                "body": "We are preparing your order",
                "custom_icon": "https://example.com/restaurant.png",
                "live_update": {
                  "op": "OPERATION_START",
                  "id": "order_4521",
                  "progress": 1,
                  "segments": [
                    { "color": "#34A853", "length": 3 },
                    { "color": "#FBBC05", "length": 4 },
                    { "color": "#4285F4", "length": 3 }
                  ],
                  "extras": { "eta": "18:40" }
                }
              }
            }
          }
        }
      },
      "schedule": { "after": "0s" },
      "message_type": "MESSAGE_TYPE_TRANSACTIONAL"
    }
  }'
```

### Push de atualização

Envie um `OPERATION_UPDATE` com o mesmo `id` sempre que a atividade avançar. Repita os segmentos e o ícone — uma atualização que os omite é renderizada sem eles.

```bash
curl -X POST https://api.pushwoosh.com/messaging/v2/notify \
  -H "Authorization: Token YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "transactional": {
      "application": "XXXXX-XXXXX",
      "platforms": ["ANDROID"],
      "users": { "list": ["customer-42"] },
      "payload": {
        "content": {
          "localized_content": {
            "default": {
              "android": {
                "title": "Order #4521",
                "body": "Your courier is on the way",
                "custom_icon": "https://example.com/restaurant.png",
                "live_update": {
                  "op": "OPERATION_UPDATE",
                  "id": "order_4521",
                  "progress": 7,
                  "segments": [
                    { "color": "#34A853", "length": 3 },
                    { "color": "#FBBC05", "length": 4 },
                    { "color": "#4285F4", "length": 3 }
                  ]
                }
              }
            }
          }
        }
      },
      "schedule": { "after": "0s" },
      "message_type": "MESSAGE_TYPE_TRANSACTIONAL"
    }
  }'
```

### Push de término

O push terminal só precisa da operação e do id.

```bash
curl -X POST https://api.pushwoosh.com/messaging/v2/notify \
  -H "Authorization: Token YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "transactional": {
      "application": "XXXXX-XXXXX",
      "platforms": ["ANDROID"],
      "users": { "list": ["customer-42"] },
      "payload": {
        "content": {
          "localized_content": {
            "default": {
              "android": {
                "live_update": {
                  "op": "OPERATION_END",
                  "id": "order_4521"
                }
              }
            }
          }
        }
      },
      "schedule": { "after": "0s" },
      "message_type": "MESSAGE_TYPE_TRANSACTIONAL"
    }
  }'
```

## Personalizar a aparência

O SDK vem com um estilo de progresso padrão construído a partir de `progress`, `progress_indeterminate` e `segments`. Para ter controle total da barra de progresso, implemente `LiveUpdateProgressStyleProvider` e modele um `Notification.ProgressStyle` você mesmo.

O provedor é o único ponto de personalização. O SDK ainda é responsável pela configuração do canal, pelos sinalizadores de andamento e promovido, pelo ícone grande, pelos botões de ação e pelo tempo do cabeçalho — um provedor personalizado só pode modelar a barra de progresso, então não pode quebrar a elegibilidade para promoção. Ele deve ser sem estado (stateless): derive o estilo retornado apenas do `LiveUpdateState` fornecido. Se ele lançar uma exceção, o SDK recorre ao estilo padrão e a notificação ainda é postada.

<Tabs>
<TabItem label="Java">
```java
import android.app.Notification;
import androidx.annotation.NonNull;
import com.pushwoosh.liveupdates.LiveUpdateProgressStyleProvider;
import com.pushwoosh.liveupdates.LiveUpdateSegment;
import com.pushwoosh.liveupdates.LiveUpdateState;
import java.util.List;

public class OrderStyleProvider implements LiveUpdateProgressStyleProvider {
    @NonNull
    @Override
    public Notification.ProgressStyle createStyle(@NonNull LiveUpdateState state) {
        Notification.ProgressStyle style = new Notification.ProgressStyle();
        if (state.getProgress() != null) {
            style.setProgress(state.getProgress());
        }
        style.setProgressIndeterminate(state.isProgressIndeterminate());

        List<LiveUpdateSegment> segments = state.getSegments();
        int boundary = 0;
        for (int i = 0; i < segments.size(); i++) {
            LiveUpdateSegment seg = segments.get(i);
            style.addProgressSegment(
                new Notification.ProgressStyle.Segment(seg.getLength()).setColor(seg.getColor()));
            boundary += seg.getLength();
            if (i < segments.size() - 1) {
                style.addProgressPoint(new Notification.ProgressStyle.Point(boundary));
            }
        }
        return style;
    }
}
```
</TabItem>
<TabItem label="Kotlin">
```kotlin
import android.app.Notification
import com.pushwoosh.liveupdates.LiveUpdateProgressStyleProvider
import com.pushwoosh.liveupdates.LiveUpdateState

class OrderStyleProvider : LiveUpdateProgressStyleProvider {
    override fun createStyle(state: LiveUpdateState): Notification.ProgressStyle {
        val style = Notification.ProgressStyle()
        state.progress?.let { style.setProgress(it) }
        style.setProgressIndeterminate(state.isProgressIndeterminate)

        val segments = state.segments
        var boundary = 0
        segments.forEachIndexed { i, seg ->
            style.addProgressSegment(
                Notification.ProgressStyle.Segment(seg.length).setColor(seg.color))
            boundary += seg.length
            if (i < segments.size - 1) {
                style.addProgressPoint(Notification.ProgressStyle.Point(boundary))
            }
        }
        return style
    }
}
```
</TabItem>
</Tabs>

Registre o provedor com uma tag `<meta-data>` no **AndroidManifest.xml**. A classe deve ter um construtor público sem argumentos.

```xml
<meta-data
    android:name="com.pushwoosh.LIVE_UPDATE_STYLE_PROVIDER"
    android:value="com.example.OrderStyleProvider" />
```

Use `LiveUpdateState.getExtras()` para ler o JSON que você enviou em `live_update.extras` e adaptar o estilo aos seus próprios dados de negócio.

## Gerenciar Live Updates a partir do seu aplicativo

O servidor controla cada `OPERATION_START`, `OPERATION_UPDATE` e `OPERATION_END`, então não há uma API do lado do aplicativo para postar ou atualizar um Live Update. A fachada `PushwooshLiveUpdates` cobre apenas o que o servidor não pode fazer — dispensar uma atualização localmente e verificar quais estão na tela.

```java
import com.pushwoosh.liveupdates.PushwooshLiveUpdates;

// Dispensa um Live Update específico quando o usuário finaliza a atividade no aplicativo,
// sem esperar pelo push terminal "end" do servidor
PushwooshLiveUpdates.endLiveUpdate("order_4521");

// Lista os IDs de atividade atualmente mostrados por este aplicativo
List<String> active = PushwooshLiveUpdates.getActiveIds();

// Limpa tudo que este aplicativo está mostrando, por exemplo, no logout
PushwooshLiveUpdates.endAllLiveUpdates();
```

Todos os métodos são seguros para serem chamados de qualquer thread e são uma operação nula (no-op) em dispositivos abaixo do Android 16.

## Links relacionados

- [Visão geral do SDK Android da Pushwoosh](/pt/developer/pushwoosh-sdk/android-sdk/)
- [Referência da API do SDK Android da Pushwoosh](https://pushwoosh.github.io/pushwoosh-android-sdk/)
- [API de Mensagens](/pt/developer/api-reference/messaging-api-v2/)
- [Notificações centradas em progresso do Android](https://developer.android.com/about/versions/16/features/progress-centric-notifications)