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 会为您设置进行中和推广标志、下载大图标、映射操作按钮并发布通知。
发送实时更新
Anchor link to您通过 Messaging API v2 发送实时更新,方法是将实时更新字段添加到 android 内容块的 root_params 对象中。使用 transactional 请求——实时更新针对的是其活动被跟踪的特定用户。schedule 字段是必需的;{ "after": "0s" } 表示立即发送。生命周期有三个操作,在 pw_live_op 中设置:
start— 活动的第一个推送。发布进行中的通知。update— 同一活动的后续推送。在原地静默刷新。end— 终止推送。关闭通知。
属于同一活动的所有推送必须共享相同的 pw_live_id。该 ID 将更新联系在一起,您也可以用它来从应用中关闭更新。
每个推送都完整地描述了通知——不会从上一个推送继承任何内容。对于每个 update,请重新发送您希望保留的每个字段,例如分段和大图标;省略的字段将被渲染为不存在。
实时更新参数
Anchor link to这些键位于 android 内容块的 root_params 对象内。标题、正文和大图标使用标准的 Android 推送字段(title、body、custom_icon)。
| 参数 | 类型 | 描述 |
|---|---|---|
pw_live_op | string | 生命周期操作:start、update 或 end。必需。 |
pw_live_id | string | 由一个实时更新的所有推送共享的稳定活动 ID。必需。 |
pw_live_progress | int | 进度值,根据分段长度总和计算。 |
pw_live_progress_indeterminate | bool | 显示不确定动画而不是具体值。 |
pw_live_segments | JSON string | 有序的进度分段,每个分段为 {"color": "#RRGGBB", "length": N}。 |
pw_live_extras | JSON string | 传递给自定义样式提供程序的任意数据。 |
pw_live_when | long | 标题时间锚点,以 epoch 毫秒为单位。 |
pw_live_chronometer | bool | 将标题时间显示为运行中的计时器。 |
pw_live_chronometer_count_down | bool | 运行中的计时器倒计时而不是正计时。 |
pw_live_show_when | bool | 是否显示标题时间列。默认为 true。 |
这四个时间字段的组合方式如下:当 pw_live_show_when 设置为 false 时,时间被隐藏;否则,pw_live_when 是锚点,pw_live_chronometer 将其变为实时计数器,而 pw_live_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", "root_params": { "pw_live_op": "start", "pw_live_id": "order_4521", "pw_live_progress": "1", "pw_live_segments": "[{\"color\":\"#34A853\",\"length\":3},{\"color\":\"#FBBC05\",\"length\":4},{\"color\":\"#4285F4\",\"length\":3}]", "pw_live_extras": "{\"eta\":\"18:40\"}" } } } } } }, "schedule": { "after": "0s" }, "message_type": "MESSAGE_TYPE_TRANSACTIONAL" } }'更新推送
Anchor link to每当活动向前推进时,发送一个带有相同 pw_live_id 的 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", "root_params": { "pw_live_op": "update", "pw_live_id": "order_4521", "pw_live_progress": "7", "pw_live_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": { "root_params": { "pw_live_op": "end", "pw_live_id": "order_4521" } } } } } }, "schedule": { "after": "0s" }, "message_type": "MESSAGE_TYPE_TRANSACTIONAL" } }'自定义外观
Anchor link toSDK 提供了一个基于 pw_live_progress、pw_live_progress_indeterminate 和 pw_live_segments 构建的默认进度样式。要完全控制进度条,请实现 LiveUpdateProgressStyleProvider 并自行塑造一个 Notification.ProgressStyle。
提供程序是唯一的自定义点。SDK 仍然负责渠道设置、进行中和推广标志、大图标、操作按钮和标题时间——自定义提供程序只能塑造进度条,因此不会破坏推广资格。它必须是无状态的:仅从提供的 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() 读取您在 pw_live_extras 中发送的 JSON,并根据您自己的业务数据调整样式。
从您的应用管理实时更新
Anchor link to服务器驱动每个 start、update 和 end,因此没有应用端的 API 来发布或刷新实时更新。PushwooshLiveUpdates 门面仅涵盖服务器无法做到的事情——在本地关闭更新并检查哪些更新正在屏幕上显示。
import com.pushwoosh.liveupdates.PushwooshLiveUpdates;
// 当用户在应用内完成活动时,关闭一个特定的实时更新,// 无需等待服务器的终止 "end" 推送PushwooshLiveUpdates.endLiveUpdate("order_4521");
// 列出此应用当前显示的活动 IDList<String> active = PushwooshLiveUpdates.getActiveIds();
// 清除此应用显示的所有内容,例如在注销时PushwooshLiveUpdates.endAllLiveUpdates();所有方法都可以安全地从任何线程调用,并且在低于 Android 16 的设备上是空操作。