Android 实时更新
Pushwoosh 通过 pushwoosh-liveupdates 模块(SDK 6.9.0 及更高版本)支持 Android 实时更新。实时更新是一种持续进行的、进度条样式的通知,系统会将其提升到锁屏、通知抽屉中,并在状态栏中显示为状态图标,这样用户无需打开您的应用即可跟踪活动。
整个生命周期由服务器驱动:您的后端在活动开始时发送一个推送,随着活动进展发送更多推送,并在活动结束时发送最后一个推送。SDK 会自动渲染每一个推送。
什么是实时更新
Anchor link to实时更新是 Android 16 (API 36) 中引入的一项功能,用于从头到尾展示用户发起的、具有时效性的活动。它们建立在平台的以进度为中心的通知和 Notification.ProgressStyle API 之上。从概念上讲,它们是 Android 平台上与 iOS 实时活动相对应的功能。
本页面仅涵盖 Pushwoosh 集成。有关平台行为、提升规则和设计指南,请参阅官方 Android 文档:
何时使用实时更新
Anchor link to实时更新适用于正在进行的、用户发起的、具有时效性的活动——即用户当前积极关心的、有明确开始和结束的事件。Pushwoosh 客户的典型场景包括:
- 食品配送 — 订单已接受、正在准备、派送中、即将送达。
- 网约车和出租车 — 已分配司机、司机在途中、即将到达、行程进行中。
- 订单和货运跟踪 — 正在运输中的订单的实时状态。
- 体育赛事和媒体直播 — 比赛进行中的比分和时间。
- 健身 — 正在进行的锻炼或跑步,显示已用时间和进度。
- 金融科技 — 正在经历各个阶段的交易或验证流程。
由于生命周期是由您的后端已经知道的真实事件(例如订单状态改变、快递员移动)驱动的,因此实时更新通常是在您现有事件流中连接的一个 API 调用,而不是由人工手动发送。
- Android 16 (API 36) 或更高版本。在较旧的设备上,该模块保持非活动状态,每个实时更新 API 调用都是安全的无操作。
- Pushwoosh Android SDK 6.9.0 或更高版本。
添加 pushwoosh-liveupdates 模块
Anchor link to将依赖项添加到您的 app/build.gradle 文件中:
dependencies { implementation 'com.pushwoosh:pushwoosh-liveupdates:<latest-version>'}请将 <latest-version> 替换为 Maven Central 上的当前版本。
该模块在启动时会自动被发现。它声明了所需的 POST_PROMOTED_NOTIFICATIONS 权限,注册了自己的通知渠道,并在默认通知路径之前拦截实时更新推送。无需额外的初始化代码——SDK 会为您设置 ongoing 和 promoted 标志、下载大图标、映射操作按钮并发布通知。
发送实时更新
Anchor link to您可以通过 Messaging API v2 发送实时更新,方法是在 android 内容块中添加一个 live_update 对象。请使用 transactional 请求——实时更新针对的是其活动被跟踪的特定用户。schedule 字段是必需的;{ "after": "0s" } 表示立即发送。生命周期有三个操作,在 live_update.op 中设置:
OPERATION_START— 活动的第一个推送。发布持续进行的通知。OPERATION_UPDATE— 同一活动的后续推送。在原地静默刷新它。OPERATION_END— 最终推送。关闭通知。
属于同一活动的所有推送必须共享相同的 live_update.id。该 ID 将更新联系在一起,也是您从应用中关闭更新时使用的 ID。
每个推送都完整地描述了通知——没有任何内容会从上一个推送继承。对于每次 OPERATION_UPDATE,请重新发送您希望保留的每个字段,例如分段和大图标;省略的字段将被渲染为不存在。
实时更新参数
Anchor link to这些键位于 android 内容块的 live_update 对象内部。标题、正文和大图标使用标准的 Android 推送字段(title、body、custom_icon),与 live_update 一同发送。
| 参数 | 类型 | 描述 |
|---|---|---|
op | string | 生命周期操作:OPERATION_START、OPERATION_UPDATE 或 OPERATION_END。必需。 |
id | string | 同一个实时更新的所有推送共享的稳定活动 ID。必需。 |
progress | int | 进度值,相对于所有分段长度的总和来衡量。 |
progress_indeterminate | bool | 显示不确定动画而不是具体值。 |
progress_bar | bool | 是否显示进度条。默认为 true。 |
segments | array | 有序的进度分段,每个分段为 { "color": "#RRGGBB", "length": N }。 |
extras | object | 传递给自定义样式提供程序的任意数据。 |
when | int64 | 头部时间锚点,以纪元毫秒为单位。 |
chronometer | bool | 将头部时间显示为运行中的计时器。 |
chronometer_count_down | bool | 运行中的计时器倒计时而不是正计时。 |
show_when | bool | 是否显示头部时间列。默认为 true。 |
四个时间字段的组合如下:当 show_when 设置为 false 时,时间被隐藏;否则 when 是锚点,chronometer 将其变为实时计数器,而 chronometer_count_down 使该计数器倒计时。
开始推送
Anchor link tocurl -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" } }'更新推送
Anchor link to每当活动向前推进时,发送一个带有相同 id 的 OPERATION_UPDATE。重复分段和图标——省略它们的更新将渲染为没有它们。
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" } }'结束推送
Anchor link to最终的推送只需要操作和 ID。
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" } }'自定义外观
Anchor link toSDK 提供了一个默认的进度条样式,该样式由 progress、progress_indeterminate 和 segments 构建。要完全控制进度条,请实现 LiveUpdateProgressStyleProvider 并自行构建一个 Notification.ProgressStyle。
该提供程序是唯一的自定义点。SDK 仍然负责渠道设置、ongoing 和 promoted 标志、大图标、操作按钮和头部时间——自定义提供程序只能塑造进度条,因此不会破坏提升资格。它必须是无状态的:仅从提供的 LiveUpdateState 派生返回的样式。如果它抛出异常,SDK 会回退到默认样式,通知仍然会发布。
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; }}import android.app.Notificationimport com.pushwoosh.liveupdates.LiveUpdateProgressStyleProviderimport 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 }}在 AndroidManifest.xml 中使用 <meta-data> 标签注册提供程序。该类必须有一个公共的无参数构造函数。
<meta-data android:name="com.pushwoosh.LIVE_UPDATE_STYLE_PROVIDER" android:value="com.example.OrderStyleProvider" />使用 LiveUpdateState.getExtras() 来读取您在 live_update.extras 中发送的 JSON,并根据您自己的业务数据调整样式。
从您的应用管理实时更新
Anchor link to服务器驱动每个 OPERATION_START、OPERATION_UPDATE 和 OPERATION_END,因此没有应用端的 API 来发布或刷新实时更新。PushwooshLiveUpdates 接口仅涵盖服务器无法完成的操作——在本地关闭更新和检查哪些更新正在屏幕上显示。
import com.pushwoosh.liveupdates.PushwooshLiveUpdates;
// 当用户在应用内完成活动时,关闭特定的实时更新,// 无需等待服务器的最终“结束”推送PushwooshLiveUpdates.endLiveUpdate("order_4521");
// 列出当前由此应用显示的活动 IDList<String> active = PushwooshLiveUpdates.getActiveIds();
// 清除此应用正在显示的所有内容,例如在注销时PushwooshLiveUpdates.endAllLiveUpdates();所有方法都可以安全地从任何线程调用,并且在 Android 16 以下的设备上是无操作。