推送(SuperSDK.push namespace)
This content is not available in your language yet.
设备推送桥接能力 · H5 通过 SuperSDK.push.* 调用。Android 需宿主集成可选模块 supersdk-push-firebase 并实现 SuperSDKProvider.getPushService()(接入见 Android 接入文档「推送」节与 SUPERPUSH.md);iOS 当前为明确的「不支持」stub(四个方法 reject UNSUPPORTED)。
SDK 只负责登记设备、把前台消息 / 点击交回 H5、上报打开;发送、受众筛选在控制台「消息推送」完成。所有接口在浏览器 / 宿主未接线 / iOS 三种环境下都给明确结果而不是报错(见下表),业务代码可以无条件调用。
| 环境 | getStatus() | 其余三个方法 |
|---|---|---|
| Android · 宿主已接线 | 真实状态(supported: true) | 正常执行 |
Android · 宿主未接线(getPushService() 为 null) | { supported: false } | reject UNSUPPORTED(Native NOT_IMPLEMENTED 经注册表归一 · retryable: false) |
| iOS(stub) | { supported: false } | reject UNSUPPORTED |
纯浏览器(无 window.appbridge) | { supported: false } | reject NOT_SUPPORTED(不抛同步异常) |
| Native 过旧(无推送 JSB) | reject SDK_TOO_OLD | reject SDK_TOO_OLD |
push.getStatus()
Section titled “push.getStatus()”获取推送状态快照。
const status = await SuperSDK.push.getStatus();// {// supported: true,// permission: 'granted', // 'granted' | 'denied' | 'prompt'// registered: true, // 存在上一次成功登记且其后无错误// lastError: 'NETWORK_ERROR', // 可选 · 最近一次登记失败原因(成功后清空)// lastOpened: { // 可选 · 一次性字段,见下方说明// messageId: 'pm_0123456789ab',// url: 'https://example.com/promo',// clickType: 'open_url', // 'open_app' | 'open_url'// openedAt: 1760000000000,// verified: true// }// }返回值: Promise<PushStatus>
| 字段 | 类型 | 说明 |
|---|---|---|
| supported | boolean | false 时其余字段省略(浏览器 / 未接线 / iOS) |
| permission | 'granted' | 'denied' | 'prompt' | 通知对用户是否可见。denied 同时覆盖「权限被拒」和「系统通知开关关闭」;prompt = Android 13+ 尚未询问过 |
| registered | boolean | 派生值:存在上一次成功登记的指纹且其后无错误。setTags 之后、新登记成功之前的瞬态仍为 true;任何登记失败(含 24h 刷新失败)翻为 false |
| lastError | string | 闭集 TOKEN_UNAVAILABLE / NOT_FOUND / INVALID_REQUEST / RATE_LIMITED / NETWORK_ERROR / UNAVAILABLE;闭集外的服务端 code 已在 Native 归一为 UNAVAILABLE。登记成功后省略 |
| lastOpened | object | 最近一次尚未被读取的推送点击,字段同 push.opened 载荷;无未读点击时省略 |
🔴
lastOpened是一次性字段:由首个读到它的getStatus()调用消费(任何 WebView 的任何一次调用,含轮询),之后不再返回。它解决的是「点击通知冷启动 App 时页面还没加载、push.opened事件没人接」这一种场景。多 WebView 下只有一个页面能读到;已经通过push.opened收到事件的页面再调getStatus()仍可能读到同一条 —— 请用push.opened事件 +lastOpened两者兜底、按messageId去重,并且不要在轮询里调用getStatus()(会把别的页面该拿到的点击抢先消费掉)。
push.requestPermission()
Section titled “push.requestPermission()”申请通知权限。Android 13+ 弹系统权限框(每台设备只会真正弹一次,之后由系统决定);Android 12 及以下不弹框,直接返回真实可达性。
const { permission } = await SuperSDK.push.requestPermission();if (permission !== 'granted') { // 引导用户去系统设置开启通知}返回值: Promise<{ permission: 'granted' | 'denied' | 'prompt' }>
交互类方法,H5 侧回调超时 120000ms(等用户操作系统弹框)。无可用前台 Activity(如后台调用)时 reject
UNAVAILABLE(retryable: true),稍后在前台重试即可。权限结果变化会触发 SDK 重新登记(控制台设备enabled随之更新)。
push.setTags(tags)
Section titled “push.setTags(tags)”设置设备标签,用于控制台按标签筛选受众。值变化时 SDK 自动重新登记;相同值不重复请求。
await SuperSDK.push.setTags(['vip', 'zh-CN']);await SuperSDK.push.setTags([]); // 清空(登记体显式带 tags: [])await SuperSDK.push.setTags(null); // 同上| 参数 | 类型 | 说明 |
|---|---|---|
| tags | string[] | null | ≤10 个,每个 ≤32 字符(按 Unicode 码点计),不含控制字符;SDK 会 trim / 去空 / 去重 / 保序。null 与 [] 等价 |
返回值: Promise<void>
边界规则由 Native 单源判定:越界 reject
INVALID_ARGUMENT(err.nativeCode === 'INVALID_PARAM',err.detail为原因)且不发请求、不落地。JSSDK 本地只拦「不是字符串数组」这类类型错误。
push.setUserId(userId)
Section titled “push.setUserId(userId)”设置业务用户 ID,用于控制台按用户定向。值变化时 SDK 自动重新登记;登出时传 null 或 '' 清除。
await SuperSDK.push.setUserId('u_123456');await SuperSDK.push.setUserId(null); // 登出:清除(登记体显式带 user_id: null)| 参数 | 类型 | 说明 |
|---|---|---|
| userId | string | null | ≤128 字符(按 Unicode 码点计),不含控制字符;null / '' = 清除 |
返回值: Promise<void>
🔴
userId与tags只是推送定向的匿名标识,不是身份认证:它们由 H5 自报、不经任何校验,服务端也不会据此信任设备身份。不要把它当作登录态,不要在推送内容里放仅凭userId就能看到的敏感信息。
push.onMessage(callback)
Section titled “push.onMessage(callback)”监听 App 在前台时收到的推送(走既有 BROADCAST 通道,事件 key push.message;SuperSDK.subscribe('push.message', cb) 等价)。后台 / 被杀态由系统直接展示通知,不经此回调。
const unsubscribe = SuperSDK.push.onMessage((message) => { // { // messageId: 'pm_0123456789ab', // title: '标题', body: '正文', imageUrl: 'https://…' | null, // url: 'https://example.com/promo' | null, // clickType: 'open_url', // 'open_app' | 'open_url' // data: { message_id: '…', url: '…', ... } // FCM data 原键透传 // }});unsubscribe(); // 页面销毁前取消返回值: 取消监听的函数。
push.onOpened(callback)
Section titled “push.onOpened(callback)”监听推送点击(事件 key push.opened)。点击系统通知或前台通知 → SDK 校验并回执 → 投递此事件 → 拉起 App(clickType === 'open_url' 且宿主未接管时由 SDK 打开 url)。
const unsubscribe = SuperSDK.push.onOpened((opened) => { // { // messageId: 'pm_0123456789ab', // url: 'https://example.com/promo', // 可选 · clickType=open_url 时存在 // clickType: 'open_url', // openedAt: 1760000000000, // verified: true // }});| 字段 | 说明 |
|---|---|
| verified | true = url / clickType 来自服务端回执(权威值);false = 点击时服务端不可达(离线 / 超时)的降级路径:url 为通知 intent 原值、未经服务端核验,SDK 此时只拉起 App、不自动打开 url。业务若要自行据 url 跳转,先检查 verified |
返回值: 取消监听的函数。
🔴 事件只投递给事件发生时已存活且已订阅的 WebView(既有 BROADCAST 语义,无监听者时直接丢弃、不缓存)。点击通知冷启动 App 时页面尚未加载,必须在页面加载后用
getStatus().lastOpened主动取一次 —— 两条路径按messageId去重即可覆盖全部场景。
错误(端内 · Error,带 code / nativeCode / retryable / detail):
err.code | 触发条件 | retryable |
|---|---|---|
NOT_SUPPORTED | 纯浏览器(无 appbridge) | - |
UNSUPPORTED | 宿主未接线(Native NOT_IMPLEMENTED)/ iOS stub | ✗ |
SDK_TOO_OLD | Native 没有推送 JSB | ✗ |
INVALID_ARGUMENT | 参数类型错误(本地)或越界(Native INVALID_PARAM) | ✗ |
UNAVAILABLE | requestPermission 无前台 Activity(Native NO_ACTIVITY) | ✓ |
TIMEOUT | 回调超时(requestPermission 120s · 其余 15s) | ✓ |