更新记录
1.2.4(2026-10-17)
- 新增 iOS 服务端图片推送的通知服务扩展源码、独立 Xcode 工程与 APNs 接入示例;需构建并集成扩展后使用顶层
imageUrl展示图片附件,下载失败或超时保留原文通知。可选imageDebug: true在原推送数据中附加图片处理诊断,供点击通知后排查。当前未附预编译扩展,仅导入插件不会启用此能力。 - 新增 uni-app / uni-app x“iOS 图片推送”示例模块,可填写 HTTPS 图片地址、通知标题和正文,生成并复制 APNs JSON、单独复制已注册的设备 Token,并复制联调日志反馈图片处理结果;页面不代发远程推送。
- 新增只读通知条件检查,按即时通知或定时提醒用途读取当前系统设置,明确返回阻断项、未确认状态和设置建议,不申请权限或发送通知。
- 新增 Android 实际通知渠道查询、指定渠道设置和电池优化设置入口,保留已有通知与精确定时设置入口。
- 新增已显示本地通知查询和按业务组清理,按业务 ID 去重计数,清理前复核当前身份,保留未来提醒、点击记录和其他 SDK 通知;部分取消失败明确返回。
- 完善 uni-app / uni-app x 示例界面与模块化接入文档,保留原通知、定时提醒、厂商推送和团队订阅 Mock 示例。
- 本次更新包含共享 UTS 和三端原生代码,使用时需安装包含当前源码的自定义基座或正式原生包。
1.2.3(2026-10-07)
- 修复 iOS 启动查询通知能力及其他通知操作的参数识别错误;保留原有公开 API、回调和 uni-app 接入方式。
1.2.2(2026-10-02)
- 修复 Android 真机运行构建因项目级仓库覆盖插件 settings 仓库而无法解析 vivo Push 4.1.7.0,并连带导致 FCM Kotlin 符号缺失的问题;改为随插件提供同版本官方原版 AAR,厂商推送 API 与行为不变。
- 修复鸿蒙同一通知频繁更新、反复展示与取消后,历史记录占用登记额度而无法继续发送的问题。
- 修复鸿蒙发布失败时无效点击记录残留的问题;保留当前有效通知和待消费点击,为在途点击保留有界历史,并兼容旧版本登记数据。
- 修复 iOS、鸿蒙单次提醒过期后仍占用登记额度的问题;过期与已取消记录改为轻量终态,释放请求快照、系统编号及私有图片/类别引用,同时保留最近状态供重复取消查询。
- 补齐 uni-app x 配对工程缺失的 Android 小米、OPPO/Heytap、vivo、魅族与 FCM 原生实现文件及本地 AAR,使其原生编译输入与 uni-app 主工程一致;该结论仅针对当前配对源码,不据此认定已发布市场包缺文件。
- 修复 64 条普通推送事件积压时冷启动点击无法优先取得的问题;冷启动点击与普通事件分别使用有界队列,普通事件不会被淘汰或提前确认,仍可由持续监听完整消费。
- Android 有限读取会携带最早冷启动点击;iOS 将 64 条限制收敛为普通消息配额,并为点击、Token 与错误事件保留总计 128 条的关键事件空间;Harmony 复用公共优先队列。
- 公开 API 和示例调用方式不变;Android、iOS、鸿蒙均需重新生成匹配当前源码的原生应用包或自定义基座,页面热更新不能更新本轮公共 UTS 与原生实现。
平台兼容性
uni-app(5.24)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| × | √ | × | × | √ | × | √ | √ | √ |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| × | × | × | × | × | × | × | × | × | × | × | × |
uni-app x(5.24)
| Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|
| × | × | √ | √ | √ | × |
其他
| 多语言 | 暗黑模式 | 宽屏模式 | 蒸汽模式 |
|---|---|---|---|
| × | × | × | √ |
lizhao-notify-pro
为 uni-app / uni-app x 提供本地通知、定时提醒、通知条件检查、分组管理与 Android、iOS、鸿蒙官方推送客户端。
介绍
为 uni-app / uni-app x 提供 Android、iOS、HarmonyOS 原生本地通知、系统定时提醒和官方推送客户端接口,用统一 API 处理展示、Token 与业务点击。
可以用它发送订单通知、预约提醒、下载进度,也可以接入官方推送通道,让用户在 APP 未打开时收到后台新消息。支持 uni-app 与 uni-app x;团队订阅等业务需要配合自己的后台,具体接入按下方模块说明完成。
功能特色
| 功能 | 可以解决什么问题 | 常用配置 |
|---|---|---|
| 普通、长文本、图片通知 | 订单结果、任务完成、图文提醒 | title、body、style |
| 业务点击与动作 | 点击消息或按钮后打开指定业务 | payloadJson、actions |
| 同 ID 管理 | 更新进度、替换内容、取消指定消息 | id、updateNotification |
| 系统定时提醒 | 一次预约、每日安排、每周事项 | trigger |
| 能力和授权查询 | 根据设备能力选择可用体验 | getNotificationCapabilities |
| 通知条件检查 | 定位权限、渠道和定时提醒的当前限制 | getNotificationDiagnostics |
| 渠道实际配置 | 查看用户设置的声音、振动和重要级别 | Android getNotificationChannel |
| 已显示通知管理 | 查看当前通知,仅清理指定业务组 | getDeliveredNotifications、cancelNotificationGroup |
| 明确的降级结果 | 图片不可用或不支持进度时使用文字 | fallback: 'text'、warnings |
| 官方厂商推送 | APP 未打开时接收后台通知 | registerPush、onPushEvent;详见模块九 |
| 团队路线上新接入示例 | 按团队通知已订阅用户 | 插件推送 + 自有后台;详见模块十 |
通知样式、调度精度和点击能力存在平台差异,详见后面的支持平台表。
适合哪些场景
| 业务场景 | 建议用法 |
|---|---|
| 订单、审批、导出完成 | 普通通知加业务透传数据 |
| 下载、上传、文件处理 | Android 进度通知;其他端先查询进度能力 |
| 预约、日程、签到 | 一次或日历重复提醒 |
| 多个订单或多个任务 | 每个业务使用独立 ID,按组归类 |
| 消息点击恢复业务 | 启动事件消费加实时点击监听 |
| 团队更新路线、上架新路线 | 后台筛选订阅用户,再发送厂商通知 |
初次使用先跑通下面的“发送第一条通知”。要实现关 APP 后的后台通知,再看厂商推送模块;一个 APP 按不同域名连接多个团队后台,继续看团队订阅模块。
下载与导入
将完整插件导入项目的 uni_modules,只从插件根目录引入 API:
import { showNotification } from '@/uni_modules/lizhao-notify-pro'
首次接入先用 HBuilderX 将本插件的原生代码和所需厂商配置打进自定义基座或正式安装包,再运行页面;已有匹配安装包时,仅调整页面/文档通常只需更新资源。
完整演示见 uni-app 示例 与 uni-app x 示例。点击接入还需将 App.vue 片段 或 App.uvue 片段 合并到现有 App 入口,保留其中的顶层静态 import;不要直接覆盖项目原有 App 文件。
体验页面时,将对应 index.vue / index.uvue 复制到项目的页面目录并在 pages.json 登记路由。顶部按“通知 / 提醒 / 推送”切换常用功能;通知与提醒页的“更多功能”可查看权限、通知条件、Android 渠道与已显示通知管理。团队订阅 Mock 在“推送”页的“更多功能”中体验,不需要业务后台。
测试真实推送时,先按模块九完成配置并开启通知权限,再到“推送”页注册设备。原厂商推送模块下方的“iOS 图片推送”可填写图片地址、标题和正文,生成并复制 APNs JSON、单独复制已注册的设备 Token,供业务后台发送。开启图片调试后,点击收到的通知回到页面,可“复制联调日志”反馈处理结果。图片推送需先完成独立扩展接入;页面本身不发送 APNs。
5 分钟跑通:发送第一条通知
在按钮点击时申请授权,获得授权后再发送消息。success 表示系统受理,实际是否弹横幅、响铃由系统设置决定。
uni-app
<template><button @click="send">发送订单提醒</button></template>
<script>
import { requestNotificationPermission, showNotification } from '@/uni_modules/lizhao-notify-pro'
export default {
methods: {
send() {
requestNotificationPermission({
success: (permission) => {
if (!permission.canPost) {
uni.showToast({ title: '请在系统设置中允许通知', icon: 'none' })
return
}
showNotification({
id: 'order-001', title: '订单提醒', body: '订单已准备完成',
success: (res) => { console.log('通知已受理:' + res.id) },
fail: (err) => { console.log('发送失败:' + err.errCode + ' ' + err.errMsg) },
complete: (res) => { console.log('操作完成:' + res.success) }
})
},
fail: (err) => { console.log('授权失败:' + err.errMsg) }
})
}
}
}
</script>
uni-app x
<template><button @click="send">发送订单提醒</button></template>
<script lang="uts">
import { requestNotificationPermission, showNotification, NotificationPermissionResult,
NotificationSubmitResult, NotificationFail, NotificationCompleteResult } from '@/uni_modules/lizhao-notify-pro'
export default {
methods: {
send() {
requestNotificationPermission({
success: (permission: NotificationPermissionResult) => {
if (!permission.canPost) {
uni.showToast({ title: '请在系统设置中允许通知', icon: 'none' })
return
}
showNotification({
id: 'order-001', title: '订单提醒', body: '订单已准备完成',
success: (res: NotificationSubmitResult) => { console.log('通知已受理:' + res.id) },
fail: (err: NotificationFail) => { console.log('发送失败:' + err.errCode + ' ' + err.errMsg) },
complete: (res: NotificationCompleteResult) => { console.log('操作完成:' + res.success) }
})
},
fail: (err: NotificationFail) => { console.log('授权失败:' + err.errMsg) }
})
}
}
}
</script>
接入方式选择
| 需要实现 | 推荐方法 | 接入要点 |
|---|---|---|
| 立即提醒 | showNotification |
先取得通知授权 |
| 点击后进入业务 | consumeInitialNotification + onNotificationClick |
页面就绪后处理,销毁时释放自己的监听 |
| 更新通知内容 | updateNotification |
复用 ID;iOS 显式允许重新投递 |
| 一次、每日、每周提醒 | scheduleNotification |
交给系统调度,查看返回的实际精度 |
| 管理定时任务 | 查询、更新、取消调度 API | 与已显示通知分开管理 |
| APP 退出后接收新消息 | registerPush + 自己后台的厂商发送接口 |
先配置通道,再上报 Token;见模块九 |
| 团队路线上新订阅 | 设备绑定 + 后台订阅关系 + 厂商推送 | 域名定位团队,后台校验成员身份;见模块十 |
从基础到进阶:按业务模块使用
下面代码放在已接入插件的页面脚本中。完整页面示例包含成功、失败、完成回调和操作按钮。
模块一:发出一条业务通知
用于 APP 正在处理订单、任务等操作时,立即把结果显示到系统通知栏。先完成通知授权,再调用下面的接口。
import { showNotification } from '@/uni_modules/lizhao-notify-pro'
showNotification({
id: 'order-002', title: '订单已完成', body: '点击查看订单详情',
payloadJson: '{"orderId":"002"}',
success: (res) => { console.log('受理编号:' + res.id) },
fail: (err) => { console.log('通知失败:' + err.errMsg) }
})
模块二:点击通知后打开业务
import { consumeInitialNotification, onNotificationClick, offNotificationClick,
NotificationClickEvent } from '@/uni_modules/lizhao-notify-pro'
// 在页面或应用的业务路由已就绪后执行,并在所属页面销毁时执行 dispose。
const handleClick = (event: NotificationClickEvent) => {
console.log('业务通知:' + event.notificationId + ',动作:' + event.actionId)
console.log('业务数据:' + event.payloadJson)
// 校验业务数据和登录状态后,再调用项目自己的导航逻辑。
}
consumeInitialNotification({
success: (res) => { if (res.event != null) handleClick(res.event!) },
fail: (err) => { console.log('读取启动通知失败:' + err.errMsg) }
})
const listenerId = onNotificationClick(handleClick)
const dispose = () => { offNotificationClick(listenerId) }
uni-app 普通 JS 脚本移除 NotificationClickEvent 类型导入、参数类型和非空断言即可。consumeInitialNotification 最多返回一个待消费启动事件,没有事件时为 null;实时监听和启动消费共用去重,不要把同一事件再次手动派发。onNotificationClick 返回空字符串表示当前未能建立监听,可在应用前台重试。
动作回调只在应用获得执行机会后触发,不提供应用退出状态下执行任意 JS 的能力。业务导航、登录等待和可靠业务处理由应用管理;可用 eventId 做业务去重。HarmonyOS 即时通知的每次投递入口只消费一次,更新通知会建立新的点击入口;系统代理提醒只负责返回应用,不产生可依赖的业务点击事件,请用应用首页提供相关业务入口。
模块三:显示长消息或图片
用于行程详情、活动海报等需要展开阅读的通知。文字优先使用长文本;图片先取得本地可读文件。
import { showNotification } from '@/uni_modules/lizhao-notify-pro'
showNotification({
id: 'journey', title: '行程安排', body: '展开查看详情', style: 'big-text',
bigText: '明天 09:00 出发。请提前准备好证件,抵达后到服务台签到。',
fail: (err) => { console.log('长文本通知失败:' + err.errMsg) }
})
uni.chooseImage({ count: 1, success: (selection) => {
if (selection.tempFilePaths.length == 0) return
showNotification({
id: 'picture', title: '图片提醒', body: '展开查看图片',
style: 'big-picture', imagePath: selection.tempFilePaths[0], fallback: 'text',
success: (res) => { console.log('实际样式:' + res.effectiveStyle + ',' + res.warnings.join(';')) },
fail: (err) => { console.log('图片通知失败:' + err.errMsg) }
})
} })
本地通知的 imagePath 只接收应用可读取的本地图片,不下载网络图片。Android / iOS 支持 _doc/、_downloads/、_www/、static/ 项目路径和应用可读的绝对路径;iOS 也支持宿主的 unifile:// 路径。定时图片应使用持久可读路径;临时文件和临时授权可能在提醒触发前失效。大图可同时传 bigText;设置 fallback: 'text' 后,图片读取或附件创建失败可改为文字通知,非法参数仍会报错。iOS 使用系统附件,Android/HarmonyOS 的展开方式由系统通知界面决定。
模块四:跟随任务更新进度
用于下载、上传和文件处理。先创建通知,再使用同一个 ID 更新进度;Android 提供原生进度条,其他平台按实际能力处理。
以下适合 Android。先创建通知,再更新相同 ID,省略的标题和业务数据保持不变。
import { showNotification, updateNotification } from '@/uni_modules/lizhao-notify-pro'
showNotification({
id: 'download-001', title: '文件下载', body: '下载中', style: 'progress',
progress: { current: 0, total: 100 }, ongoing: true, autoCancel: false,
silent: true, android: { onlyAlertOnce: true },
success: () => {
updateNotification({
id: 'download-001', progress: { current: 50, total: 100 },
fail: (err) => { console.log('更新进度失败:' + err.errMsg) }
})
},
fail: (err) => { console.log('创建进度通知失败:' + err.errMsg) }
})
// 真实业务完成后再调用:
// updateNotification({ id: 'download-001', body: '下载完成',
// progress: { current: 100, total: 100 }, ongoing: false, autoCancel: true })
iOS 没有此类原生进度条;可设置 fallback: 'text',省略 ongoing 和 autoCancel: false,将进度作为文字显示。更新已显示通知必须传 replaceDelivered: true,返回 reposted,不适合高频进度刷新。HarmonyOS 先查询进度能力,模板不可用时可明确选择文字替代。
Android 也不建议把每个网络数据包的进度回调直接提交成通知更新;系统可能丢弃过密更新。业务层可按可见进度变化降低刷新频率,并确保完成或失败状态最终提交。插件不会静默合并调用或改变每次调用的 success / fail / complete 语义;本轮仅复用同一次操作内的系统查询结果。Android 官方更新限制
模块五:安排一次预约提醒
用于已经知道提醒时间的预约、日程。APP 预先把时间交给系统;后台以后新发布的路线应使用模块九的远程推送。
import { scheduleNotification } from '@/uni_modules/lizhao-notify-pro'
scheduleNotification({
id: 'appointment', title: '预约提醒', body: '预约将在十分钟后开始',
trigger: { type: 'once', at: Date.now() + 10 * 60 * 1000 },
success: (res) => { console.log('已安排:' + res.id + ',实际精度:' + res.precision) },
fail: (err) => { console.log('安排失败:' + err.errCode + ' ' + err.errMsg) }
})
at 为未来的毫秒时间戳。默认不请求精确闹钟。仅 Android 可设置 exact: true;授权不足时默认失败,允许延迟时再设置 allowInexactFallback: true 并检查 precision、warnings。HarmonyOS 系统提醒需应用具备对应的代理提醒权限和权益,不支持动作和业务点击透传;请省略 actions / payloadJson。
模块六:每天或每周提醒
用于签到、固定日程等按时间重复的提醒。下面以每周一、三、五 09:00 为例。
import { scheduleNotification, updateScheduledNotification, getScheduledNotifications,
cancelScheduledNotification } from '@/uni_modules/lizhao-notify-pro'
scheduleNotification({
id: 'weekly-plan', title: '每周安排', body: '查看今天的事项',
trigger: { type: 'weekly', hour: 9, minute: 0, weekdays: [1, 3, 5] },
fail: (err) => { console.log('每周提醒失败:' + err.errMsg) }
})
// 改为每天 08:30,保留原内容:
// updateScheduledNotification({ id: 'weekly-plan', trigger: { type: 'daily', hour: 8, minute: 30 } })
// getScheduledNotifications({ success: (res) => { console.log('任务列表:' + JSON.stringify(res.items)) } })
// cancelScheduledNotification({ id: 'weekly-plan' })
每日和每周按设备当地时间计算;星期 1 表示周一,7 表示周日。Android / iOS 还支持 { type: 'interval', intervalSeconds: 60 },间隔范围为 60–2147483647 整数秒。firstAt 只适用于 Android。iOS 更新间隔提醒的内容会重新计时,结果通过 warnings 提示;普通查询不会重新开始倒计时。跨时区、夏令时、节电、专注模式及系统配额都可能影响实际送达。
模块七:分类、动作和清理
用于多个订单、任务共存时分别管理通知。使用独立 ID 避免互相覆盖,分组帮助用户识别同类消息。
import { showNotification, cancelNotification, cancelAllNotifications } from '@/uni_modules/lizhao-notify-pro'
showNotification({
id: 'order-actions', title: '订单待处理', body: '选择要打开的页面',
group: { id: 'orders' }, payloadJson: '{"orderId":"003"}',
actions: [
{ id: 'details', title: '查看详情', payloadJson: '{"page":"detail","orderId":"003"}' },
{ id: 'list', title: '订单列表', payloadJson: '{"page":"list"}' }
],
fail: (err) => { console.log('交互通知失败:' + err.errMsg) }
})
// cancelNotification({ id: 'order-actions' })
// cancelAllNotifications({ scope: 'delivered' }) // 只清理已显示通知
// cancelAllNotifications({ scope: 'scheduled' }) // 只取消定时任务
// cancelAllNotifications({ scope: 'all' }) // 两类都清理
最多两个前台动作,点击后回调包含独立 actionId 和该动作的 payloadJson;省略动作数据时为 '{}'。分组只影响系统归类,不保证折叠外观。批量清理只处理本插件登记的通知与任务。
Android 可先创建业务渠道,再通过 android.channelId 使用:
import { createNotificationChannel, showNotification } from '@/uni_modules/lizhao-notify-pro'
createNotificationChannel({
channelId: 'orders', channelName: '订单提醒', importance: 'high',
success: () => {
showNotification({ title: '订单更新', body: '有一条新进展', android: { channelId: 'orders' } })
},
fail: (err) => { console.log('创建渠道失败:' + err.errMsg) }
})
Android 8 及以上的渠道重要性、声音等首次建立后受系统和使用者管理,重复创建无法强制重置设置。其他平台调用渠道 API 返回不支持。
模块:检查通知条件
用户已允许通知却没有看到提醒时,可以先读取当前应用设置,区分已关闭、无需配置、系统不支持和无法确认的条件。检查不会申请权限、创建渠道或发送测试通知。
import { getNotificationDiagnostics, GetNotificationDiagnosticsResult } from '@/uni_modules/lizhao-notify-pro'
getNotificationDiagnostics({
purpose: 'scheduled', exact: false,
success: (res: GetNotificationDiagnosticsResult) => {
res.checks.forEach((check) => {
console.log(check.message, check.state, check.blocking, check.action)
})
},
fail: (err) => { console.log(err.errCode, err.errMsg) }
})
立即通知使用 purpose: 'immediate',定时提醒使用 scheduled;仅 Android 精确定时业务需要同时设置 exact: true。Android 可传 channelId 检查指定渠道,HarmonyOS 可传 harmonySlotType 检查实际业务槽位。
blocking: true 表示当前条件会阻止对应业务;unknown 表示无法确认。没有阻断项也不保证某条通知一定展示、响铃或按时送达。专注模式、厂商后台策略和签名权益等无法可靠读取时,会保留为未确认状态。检查中的 action 是可供用户点击的设置建议,不会自动跳转。
模块:读取 Android 渠道实际配置
首次创建渠道后,重要级别、声音和振动可能由用户在系统中修改。读取实际配置可以帮助定位某一类消息无法提醒的原因;查询不会创建或重置渠道,需要 Android 8 及以上。
import { getNotificationChannel, GetNotificationChannelResult } from '@/uni_modules/lizhao-notify-pro'
getNotificationChannel({
channelId: 'orders',
success: (res: GetNotificationChannelResult) => {
if (!res.exists) { console.log('渠道尚未创建'); return }
console.log('渠道是否开启:', res.enabled, '实际重要级别:', res.importance)
console.log('声音:', res.sound, '振动:', res.vibration, '角标:', res.showBadge)
},
fail: (err) => { console.log(err.errCode, err.errMsg) }
})
exists: false 与已创建但关闭是两种状态。不存在时可先调用 createNotificationChannel;重复创建不能强制改回用户的设置。需要引导时,在用户点击按钮后打开对应设置:
import { openNotificationSettings } from '@/uni_modules/lizhao-notify-pro'
function openOrderChannelSettings() {
openNotificationSettings({
section: 'channel', channelId: 'orders',
success: () => { console.log('已打开设置,返回后重新查询') },
fail: (err) => { console.log(err.errCode, err.errMsg) }
})
}
Android 6 及以上可使用 section: 'battery-optimization' 打开系统电池优化列表,由用户选择应用并调整;打开页面不代表设置已经改变。iOS、HarmonyOS 对这两个 Android 专属入口及渠道查询返回 9082004。
模块:按业务组管理已显示通知
订单、下载或团队通知可使用 group: { id: 'orders' } 保存业务分组。列表读取系统当前仍在显示的本插件本地通知,不消费点击、不读取其他 SDK 或厂商远程推送的消息正文。
import { getDeliveredNotifications, GetDeliveredNotificationsResult } from '@/uni_modules/lizhao-notify-pro'
getDeliveredNotifications({
groupId: 'orders',
success: (res: GetDeliveredNotificationsResult) => {
res.items.forEach((item) => { console.log(item.id, item.groupId, item.title, item.body) })
console.log(res.warnings)
},
fail: (err) => { console.log(err.errCode, err.errMsg) }
})
省略 groupId 可查看全部业务组,显式空字符串会报参数错误。列表按业务 ID 选择最新显示记录,通知被用户点击或清除后可能不再出现在列表中。postedAt 是显示时间的毫秒时间戳,系统无法提供时为 0;observedAt 是本次查询的时间。业务组取自 group.id,iOS 的 ios.threadId 可以另设,不会改变业务组。
用户明确清理某个业务组时,单独调用:
import { cancelNotificationGroup, CancelNotificationGroupResult } from '@/uni_modules/lizhao-notify-pro'
function clearOrderNotifications() {
cancelNotificationGroup({
groupId: 'orders',
success: (res: CancelNotificationGroupResult) => {
console.log('匹配:', res.matchedCount, '取消命令已提交:', res.submittedCount)
console.log('未取消:', res.failedIds, '提示:', res.warnings)
},
fail: (err) => { console.log(err.errCode, err.errMsg) }
})
}
清理必须提供非空合法业务组,不会扩大为清理全部。它仅取消该组当前已显示的通知,保留未来提醒和待消费点击;要停止后续提醒,另用 cancelScheduledNotification。submittedCount 表示系统接受取消命令的业务条数,不表示已核实通知消失;可再查询列表确认当前状态。通知已换组、重投递或不再显示时会跳过并返回提示;部分失败保留在 failedIds。重复清理没有目标时返回零条。
列表与按组清理支持 Android 6、iOS 12、HarmonyOS API 12 及以上;低版本返回 9082004。HarmonyOS 当前仅管理本插件即时本地通知,系统代理提醒的已显示通知不在此列表中。旧 iOS 通知若无法恢复业务分组快照,会跳过并返回提示。
模块八:按设备能力选择体验
import { getNotificationCapabilities, getNotificationPermission,
openNotificationSettings } from '@/uni_modules/lizhao-notify-pro'
getNotificationCapabilities({
success: (res) => {
console.log('进度能力:' + res.capabilities.progress.state)
console.log('进度能力说明:' + res.capabilities.progress.reason)
console.log('定时点击透传:' + res.capabilities.scheduledClickPayload.state)
},
fail: (err) => { console.log('能力查询失败:' + err.errMsg) }
})
getNotificationPermission({
success: (res) => { console.log('可展示:' + res.canPost + ',可调度:' + res.canSchedule) }
})
// 用户选择去设置时再调用:
// openNotificationSettings({ section: 'notification' })
// Android 精确定时:openNotificationSettings({ section: 'exact-alarm' })
能力为 supported / unsupported / unknown,能力支持不等于已经取得授权;unknown 时先按不依赖该能力的方式展示,并处理实际调用的失败结果。
模块九:厂商推送——APP 未打开时接收新消息
适用于后台新订单、团队路线上新等“服务器刚发生的新消息”。手机端先注册得到推送地址(Token),业务后台再向对应厂商发送通知栏消息。showNotification 只在应用有执行机会时发本地通知,不能代替服务端推送。
按这个顺序接入:
- 在下表对应的官方平台创建应用,完成包名、签名和客户端配置;使用已包含这些配置的安装包。
- 用户同意隐私政策后,点按钮申请通知权限并调用
registerPush。 - 将返回的 Token 和通道上报自己的 HTTPS 后台;Token 更新时重新上报。
- 后台向该设备发送一条通知栏消息,分别检查通知展示和点击回调。团队订阅继续看模块十。
| 平台 | 官方客户端 | 使用条件 | 进程退出后系统通知 |
|---|---|---|---|
| Android | 华为、荣耀、小米、OPPO/Heytap、vivo、魅族、FCM | 对应厂商系统服务、账号、包名与签名;FCM 需要可用的 Google Play 服务 | 通知权限和服务端发送配置齐全时由官方通道处理;用户强制停止后不作保证 |
| iOS | APNs | 已签名的 Push Notifications 能力 | 使用 APNs alert 推送,由系统展示;静默推送不能替代通知栏消息 |
| HarmonyOS | Push Kit 普通通知 | AGC 开通且签名匹配 | 服务端发送普通通知时由系统处理,不包含扩展通知 |
getPushCapabilities 说明当前安装包和设备的客户端能力;supportedProviders 是插件包含的通道,available 不表示已取得 Token 或已验收送达。设备或配置不满足条件时会明确返回原因。请在用户同意隐私政策后,在前台申请通知授权,再注册推送:
import {
requestNotificationPermission, getPushCapabilities, registerPush,
onPushEvent, offPushEvent, consumeInitialPushEvent
} from '@/uni_modules/lizhao-notify-pro'
let pushListenerId = ''
// 页面启动时先消费系统点击,再监听后续 Token、前台消息和点击。
consumeInitialPushEvent({
success: ({ event }) => {
if (event?.kind == 'click') console.log('冷启动推送点击:' + event.payloadJson)
},
fail: (error) => { console.log('读取推送点击失败:' + error.errCode) }
})
pushListenerId = onPushEvent((event) => {
if (event.kind == 'token') {
// 在此调用自己的 HTTPS 接口,把 provider/platform/token 与当前用户绑定。
console.log('推送 Token 已更新:' + event.provider)
} else if (event.kind == 'click') {
console.log('推送点击:' + event.payloadJson)
}
})
// 用户操作后调用;先按下表配置当前 Android 厂商,省略 provider 时自动选择。
requestNotificationPermission({
success: (permission) => {
if (!permission.canPost) {
console.log('请先在系统设置中允许通知')
return
}
registerPush({
// 华为:provider: 'huawei', appId: '你的 AGC 应用 App ID',
// 鸿蒙:provider: 'harmony', clickPublicKey: 'Base64 编码的 RSA SPKI 公钥',
success: ({ provider, platform, token, installationId }) => {
// 必须将 Token 与 Android/Harmony installationId 上报自己的服务端;不要写进公开日志。
console.log('厂商推送已注册:' + platform + '/' + provider)
},
fail: (error) => { console.log('厂商推送注册失败:' + error.errCode + ' ' + error.errMsg) }
})
},
fail: (error) => { console.log('通知授权失败:' + error.errMsg) }
})
// 页面卸载时调用 offPushEvent(pushListenerId)。
getPushToken 只读取已经注册取得的 Token;尚未产生时返回 9082014。iOS 会读取本机缓存的最近一次真实 APNs Token,应用每次启动仍应调用 registerPush 向系统刷新。registerPush 失败时不返回空 Token 冒充成功。consumeInitialPushEvent 返回 { event: null } 表示没有待处理的冷启动点击;事件在页面回调和 complete 结束后才确认原生记录。payloadJson 限制为有效 JSON 且最多 8192 个 UTF-8 字节。页面收到点击后仍要核验登录态和业务 ID,再跳转。监听用 offPushEvent(listenerId) 精确释放。
Android 普通透传消息最多保留 64 条未消费记录;有效签名点击和每个厂商的最新 Token 事件不占用该普通消息配额。读取仍按有限批次进行,事件经页面消费确认后删除。业务应及时订阅并消费事件,不能把客户端收件箱当作无限期消息归档;磁盘满、数据库损坏或持久化前进程被终止仍可能使事件无法保存,诊断日志不会包含 Token 或业务正文。旧版数据库升级时,对没有待发 Token 事件的通道补发缓存的最近 Token,服务端绑定处理应保持幂等。
Android 点击中转页对明确可恢复的存储故障最多额外重试三次(间隔 250/1000/3000 毫秒),页面销毁后取消;不可恢复错误不等待重试。最终未能保存时会打开宿主并仅转交插件所需的签名字段,供后续生命周期再次校验和尝试,不代表事件已经入库。
Android 接入:展开查看厂商参数、宿主配置与通知点击
#### Android 客户端配置 Android 根据设备品牌选择对应通道:小米/Redmi、OPPO/OnePlus/realme、vivo/iQOO、魅族、华为或荣耀;其他设备优先尝试有 Google Play 服务的 FCM。旧荣耀机型不支持荣耀服务但具备 HMS 时,以及未知品牌没有 GMS 但具备 HMS 时,继续使用华为通道。品牌只是候选条件,最终还要满足 SDK 和系统服务要求;不会因为品牌匹配就伪造注册成功。可以显式传 `provider` 测试指定通道。 | 参数 | 类型 | 必填 | 说明 | 默认值 | 可选参数 | | --- | --- | --- | --- | --- | --- | | provider | PushProvider | 否 | 指定通道;iOS/鸿蒙仍使用各自平台通道 | 自动选择 | xiaomi / huawei / honor / oppo / vivo / meizu / fcm / apns / harmony | | appId | string | 按通道 | 华为、小米、魅族客户端 App ID;vivo 以 Manifest 配置为准 | 宿主配置 | 最长 128 字符,字母、数字、点、下划线、短横线 | | appKey | string | 按通道 | 小米、OPPO、魅族客户端 AppKey;vivo 以 Manifest 配置为准 | 宿主配置 | 最长 256 个非空白 ASCII 字符 | | oppoAppSecret | string | OPPO 按配置 | Heytap 客户端注册要求的 AppSecret,与服务端 MasterSecret 不同 | 宿主配置 | 最长 256 个非空白 ASCII 字符 | | clickPublicKey | string | 鸿蒙业务点击 | RSA SPKI 公钥;Android 使用下方 Manifest 公钥配置 | 空 | 标准 Base64 | | success / fail / complete | function | 否 | 异步返回真实 Token、错误及完成结果;一次请求最多完成一次 | 无 | 沿用原有回调签名 | 小米、OPPO、魅族可以显式传入客户端配置,也可在宿主 Manifest 中设置默认值。以下是注册调用形态,示例占位值须替换为自己厂商后台的客户端配置: ```ts // 小米和魅族分别调用各自通道;业务按当前设备选择其中一个。 registerPush({ provider: 'xiaomi', appId: 'YOUR_MI_APP_ID', appKey: 'YOUR_MI_APP_KEY', success: (res) => { console.log('小米推送注册成功') }, fail: (err) => { console.log('小米推送注册失败:' + err.errCode) } }) // OPPO 的 AppSecret 是 SDK 必需客户端配置;不要填服务端 MasterSecret。 registerPush({ provider: 'oppo', appKey: 'YOUR_OPPO_APP_KEY', oppoAppSecret: 'YOUR_OPPO_APP_SECRET', success: (res) => { console.log('OPPO 推送注册成功') }, fail: (err) => { console.log('OPPO 推送注册失败:' + err.errCode) } }) ``` 宿主 AndroidManifest 的 `iOS APNs 配置
宿主打包时启用 push 模块与 Push Notifications 能力,配置与签名匹配的 aps-environment。APNs .p8 密钥只保存在业务服务端;DCloud 生命周期 Hook用于取得设备 Token,通知代理与启动参数分别接管前台消息和冷启动点击。旧基座不会因为页面热更新而新增 APNs 注册 Hook,需重新生成并安装已签名的原生包。
服务端图片推送: 用于活动海报、订单配图等通知内容。服务端在 APNs payload 顶层传 imageUrl,并设置 aps.mutable-content: 1 与包含标题、正文的 aps.alert:
{
"aps": {
"alert": { "title": "订单已发货", "body": "查看包裹详情" },
"mutable-content": 1,
"sound": "default"
},
"pushEventId": "shipment-20261017-001",
"imageUrl": "https://cdn.example.com/notice.jpg",
"imageDebug": true,
"orderId": "order-001"
}
图片显示为通知附件,缩略图和展开效果由 iOS 决定,应用图标仍保留。需先按图片推送接入示例构建并集成独立通知服务扩展;当前提供扩展源码和 Xcode 工程,未包含预编译 .appex,只导入插件或增加服务端字段不会生效。图片应使用无需 App 登录态的 HTTPS 地址;下载失败或超时保留原文通知。uni-app 与 uni-app x 使用同一套接入方式,页面继续通过已有 onPushEvent / consumeInitialPushEvent 处理点击。
imageDebug: true 仅用于联调,生产可移除;扩展处理后会在原 payloadJson 的 imageDebugResult 中附加结果、原因及耗时等诊断。点击通知回到示例页面后,使用“复制联调日志”反馈,并保留日志里的示例版本和构建标记;内容会脱敏,诊断不包含图片地址或设备 Token。未取得诊断不能证明扩展成功运行或消息必达,排查方法见上方接入示例。
HarmonyOS Push Kit 配置
在 AGC 开通 Push Kit,使用对应应用签名。宿主主 Ability 的 skills.actions 需包含 action.ohos.push.listener,并只指定一个 Ability 监听。注册时调用 registerPush({ provider: 'harmony', clickPublicKey: 'Base64 编码的 RSA SPKI 公钥' }),将返回的 installationId 与 Token 一并上报业务服务端。私钥只能保存在服务端。
服务端普通通知的 payload.notification.clickAction.data 要映射为启动 Want 的 parameters,包含 lizhaoPushOwner='lizhao-notify-pro'、lizhaoPushEventId、lizhaoPushPayloadJson(原始 JSON 字符串)、lizhaoPushInstallationId、lizhaoPushExpiresAt(13 位 Unix 毫秒字符串)和 lizhaoPushSignature(标准 Base64)。服务端用 RSA PKCS#1 v1.5 / SHA-256 签署下列 UTF-8 原文,换行符为 \n,不能改变 JSON 字符串中的空白:
lizhao-notify-pro.click.v1\n<bundleName>\nharmony\n<eventId>\n<installationId>\n<expiresAt>\n<payloadJson>
缺少公钥、签名无效、过期或安装实例不匹配时,点击只打开 App,不派发业务 kind:'click'。当前 HBuilderX 5.24 的 Push Kit 声明未提供普通通知 DEFAULT 类型的 receiveMessage 前台回调,所以不能承诺普通通知产生 kind:'message' 页面事件;前台普通通知展示按服务端 notification.foregroundShow 和系统规则处理。详见鸿蒙普通通知发送说明和 Push Kit API。改动原生 Ability 配置后需重新生成并安装 HarmonyOS 包。
服务端与错误码
业务服务端保存 {用户或安装实例, provider, platform, token},Token 轮换时覆盖旧值,按 provider 选择对应厂商发送 API。服务端鉴权与离线消息策略由业务系统维护。推送接口新增错误码:9082013 厂商或签名配置缺失,9082014 Token 尚未取得;既有 9082001 参数错误、9082004 平台不支持、9082011 原生桥接/SDK 失败继续适用。没有对应厂商账号、签名包与设备的情况下,静态编译和假对象回归不能证明关 App 送达成功。
模块十:团队路线上新订阅——一个团队一个后台
解决什么问题: 同一个 APP 根据团队域名连接不同后台。用户订阅某团队的“路线上新”,该团队发布或更新路线时,后台只向有权限且已订阅的用户发送通知;点击后进入对应路线。
插件负责设备推送注册、Token 和点击事件。团队管理、订阅开关、路线发布和服务端发送接口由你的业务后台实现。onPushEvent 是手机端事件监听,不等于已经在后台订阅了某个团队,也不是微信小程序订阅消息接口。
先体验:示例页里的 Mock 模块
打开 uni-app 示例 或 uni-app x 示例,找到“团队路线上新 · Mock”:
- 查看当前演示团队和域名,点击“模拟绑定设备”。
- 点击“订阅路线上新”,观察模块内状态变为“已订阅”。
- 点击“模拟发布路线”,生成一条本页演示通知。
- 点击“预览通知点击”,在模块内查看路线详情预览。
- 点击“取消订阅”,再模拟发布,当前用户不再产生新提醒;已有提醒不会被撤回。
- 切换到另一个演示团队后,重新绑定、订阅;直接点击上一团队的通知会提示先切换并核验权限。
此卡片使用内存 Mock 数据,离开页面后重置;不会调用网络、上传真实 Token 或发送系统通知。真实推送注册仍由示例页“厂商推送”卡片调用插件公开 API。Mock 跑通说明理解了业务流程,真实离线送达还需完成下面的后台接入。
第一步:明确团队、用户、设备的关系
| 数据 | 从哪里获得 | 用来做什么 |
|---|---|---|
teamId |
用户登录或进入团队后,由业务后台返回 | 隔离团队、查询成员和订阅 |
domain / apiBase |
自己维护的可信团队域名映射 | 选择团队后台的 HTTPS 地址 |
| 用户身份 | 业务登录凭据 | 后台识别当前用户;不信任前端自填的 userId |
provider / platform / token |
registerPush 或 getPushToken 的真实返回 |
确定发送通道和目标设备 |
installationId |
Android/Harmony 的 Token 结果 | 绑定当前安装实例,生成通知点击签名;iOS 可不传 |
bindingId |
自己的设备绑定接口返回 | 保存本机在当前团队和账号下的绑定记录,供 Token 更新和解绑使用 |
topic: 'route_update' |
本例定义的业务分类 | 表示订阅“路线上新”,不是插件 API 或厂商主题参数 |
routeId |
路线发布后台 | 点击通知后查询对应路线 |
域名只是寻找团队后台的入口,不能代替登录和成员权限。不要把推送内容中的任意域名直接当作请求地址;先与可信映射核对,再使用该团队自己的登录凭据。多个后台共用一个 APP 时,可由统一推送服务保管厂商发送凭据,各团队后台提交经过鉴权的发布事件。
第二步:业务后台准备这些接口
下面是建议的业务接口合同,路径可按自己的后台调整,插件不提供这些 HTTP 接口。除登录流程外均要求业务登录凭据,后台校验团队成员身份;返回 JSON 的 code=0 才表示业务成功。
| 接口 | 请求/结果 | 用途 |
|---|---|---|
GET /api/team-context |
返回 teamId / domain;示例 {"code":0,"data":{"teamId":"team-a","domain":"team-a.example"}} |
登录后确认当前团队 |
PUT /api/push/devices |
上传 teamId / provider / platform / token / installationId / bindingId,首次 bindingId 为空;成功 {"code":0,"data":{"bindingId":"binding-001"}} |
幂等绑定设备,后续携带绑定编号替换轮换后的 Token |
PUT /api/subscriptions/route-update |
{"teamId":"team-a","topic":"route_update","enabled":true};成功 {"code":0} |
订阅;enabled:false 为取消 |
GET /api/subscriptions/route-update |
返回 {"code":0,"data":{"enabled":true}} |
重新进入页面时恢复后台订阅状态 |
DELETE /api/push/devices |
上传 teamId / bindingId,用户由登录凭据识别;成功 {"code":0} |
退出登录或按产品规则解除当前设备绑定 |
GET /api/routes/{routeId} |
路线详情;无权限返回 HTTP 403,已删除返回 404 | 点击后再次校验路线所属团队和访问权限 |
后台生成并返回 bindingId,前端按“后台地址 + 团队 + 当前账号”保存到本机;它不是登录凭据。再次上报时,后台必须验证该编号属于当前团队、登录用户和原设备通道,不能仅凭客户端编号更新他人记录。首次请求重试按同一团队、用户、通道和 Token 幂等处理;已有编号时仅更新该设备记录,不覆盖同一用户的其他手机。缓存丢失时重新绑定并清理失效记录,不猜测其他设备的编号。订阅记录按“团队 + 用户 + 分类”唯一保存,设备单独保存。前端收到 HTTP 200 也要检查 code,失败时保留原订阅状态并提示重试。
第三步:把真实 Token 上报,并保存订阅开关
先完成模块九的厂商配置。下面两份代码任选与你项目一致的一份,放在自己的业务页面脚本中;把团队信息换成已核验的登录结果、把空登录凭据接到自己的登录状态。.example 是演示域名,不能直接作为正式后台使用。
uni-app:复制设备绑定和订阅请求代码
```js import { registerPush, requestNotificationPermission } from '@/uni_modules/lizhao-notify-pro' // 来自已核验的登录结果和可信配置;不从推送 payload 直接取请求地址。 const team = { teamId: 'team-a', apiBase: 'https://team-a.example' } let accessToken = '' // 填入当前团队业务登录凭据,不是推送 Token。 let subscribed = false // 页面实际使用时放到 data/ref,进入页面先向后台查询。 const currentUserId = 'user-001' // 替换为登录结果中的账号 ID,仅用于本机缓存隔离。 const bindingCacheKey = 'notify-binding:' + encodeURIComponent(team.apiBase) + ':' + encodeURIComponent(team.teamId) + ':' + encodeURIComponent(currentUserId) const cachedBindingId = uni.getStorageSync(bindingCacheKey) let bindingId = typeof cachedBindingId === 'string' ? cachedBindingId : '' function putTeamSetting(path, data, done) { if (accessToken.length === 0) { uni.showToast({ title: '请先登录当前团队', icon: 'none' }) return } uni.request({ url: team.apiBase + path, method: 'PUT', data, header: { Authorization: 'Bearer ' + accessToken, 'Content-Type': 'application/json' }, success: (res) => { if (res.statusCode === 200 && res.data != null && res.data.code === 0) { done(res.data) } else { uni.showToast({ title: '后台未保存,请检查登录或权限', icon: 'none' }) } }, fail: () => { uni.showToast({ title: '网络异常,未保存,请重试', icon: 'none' }) } }) } // 在真实 registerPush/getPushToken 的 success 中调用;不要打印 Token。 function bindTeamDevice(device) { putTeamSetting('/api/push/devices', { teamId: team.teamId, provider: device.provider, platform: device.platform, token: device.token, installationId: device.installationId ?? '', bindingId }, (body) => { const nextBindingId = body.data != null ? body.data.bindingId : null if (typeof nextBindingId !== 'string' || nextBindingId.length === 0) { uni.showToast({ title: '后台未返回设备绑定编号', icon: 'none' }) return } bindingId = nextBindingId uni.setStorageSync(bindingCacheKey, bindingId) // 下次启动、Token 轮换和退出解绑复用。 uni.showToast({ title: '设备已绑定,可选择订阅', icon: 'none' }) }) } // 用户点“绑定设备”后调用;先取得隐私同意,并确认当前团队已登录。 function enableTeamPush() { if (accessToken.length === 0) { uni.showToast({ title: '请先登录当前团队', icon: 'none' }) return } requestNotificationPermission({ success: (permission) => { if (!permission.canPost) { uni.showToast({ title: '请在系统设置允许通知', icon: 'none' }) return } registerPush({ success: bindTeamDevice, fail: (err) => { uni.showToast({ title: '注册失败:' + err.errCode, icon: 'none' }) } }) }, fail: () => { uni.showToast({ title: '通知授权未完成', icon: 'none' }) } }) } // 订阅按钮调用 setRouteSubscription(true),取消按钮传 false;网络请求期间禁用按钮。 function setRouteSubscription(enabled) { putTeamSetting('/api/subscriptions/route-update', { teamId: team.teamId, topic: 'route_update', enabled }, () => { subscribed = enabled // 仅在后台确认后更新;取消不影响此前已发送的通知。 uni.showToast({ title: enabled ? '已订阅路线上新' : '已取消订阅', icon: 'none' }) }) } ```uni-app x:复制对应的强类型请求代码
```ts import { registerPush, requestNotificationPermission, PushTokenResult, NotificationPermissionResult, NotificationFail } from '@/uni_modules/lizhao-notify-pro' // 团队与 HTTPS 地址来自可信登录上下文;下面都是待替换的演示配置。 const teamId: string = 'team-a' const apiBase: string = 'https://team-a.example' let accessToken: string = '' // 当前团队的业务登录凭据。 let subscribed: boolean = false // 页面中改为 data/ref,初始值从业务后台读取。 const currentUserId: string = 'user-001' // 替换为登录结果中的账号 ID,仅用于缓存隔离。 const bindingCacheKey = 'notify-binding:' + encodeURIComponent(apiBase) + ':' + encodeURIComponent(teamId) + ':' + encodeURIComponent(currentUserId) const cachedBindingId = uni.getStorageSync(bindingCacheKey) let bindingId: string = typeof cachedBindingId == 'string' ? cachedBindingId as string : '' function putTeamSetting(path: string, data: UTSJSONObject, done: (body: UTSJSONObject) => void): void { if (accessToken.length == 0) { uni.showToast({ title: '请先登录当前团队', icon: 'none' }) return } uni.request上面是单次接入片段,生产页面还需接好这几个生命周期:
onPushEvent收到kind:'token'时,用同一provider调用getPushToken,取得包含installationId的完整结果,再调用bindTeamDevice。只更新设备记录,不自动替用户开启已取消的订阅。- 应用启动先恢复当前团队、账号对应的
bindingId,再注册/上报 Token;上报失败保留“待同步”状态,在网络恢复或下次启动时重试。退出登录用旧团队凭据和该bindingId调用 DELETE,后台确认解绑后再清理缓存与登录态;解绑失败提示重试或按业务退出策略处理,不能把本机清缓存当作后台已解绑。 - 切换团队前等当前请求结束或取消请求;旧团队请求的回调不得更新新团队页面。每个团队使用自己的凭据,不能把 A 团队的登录信息发给 B 团队域名。
- 进入订阅页面调用 GET 接口恢复真实开关;提交期间禁用重复点击。若产品只接收“当前团队”,切换时解除旧团队设备绑定;若允许多团队订阅,各团队分别保留关系并在点击时核验权限。
第四步:团队后台发布路线并发送
发布或更新路线成功后,由后台查找该团队 route_update 已启用且仍有访问权限的用户,再查询这些用户有效的设备 Token,按 provider 调用对应官方发送接口。推荐保留一份站内消息,用于用户重新联网后查询未读内容。
这是发送时携带的业务 payload,不是可直接提交给任意厂商的完整请求:
{
"type": "route_update",
"teamId": "team-a",
"domain": "team-a.example",
"routeId": "route-001"
}
标题例如“山野团队上新路线”,正文例如“周末山谷徒步已发布,点击查看”。iOS 使用 APNs alert,Android 使用厂商通知栏消息,Harmony 使用普通通知。Android/Harmony 要进入业务详情,还应按模块九的点击协议生成签名并带上安装实例等字段;仅发送上面的 JSON 不足以产生通过校验的业务点击事件。
后台对“路线发布事件 + 用户 + 设备”做发送去重,处理失效 Token 和失败重试。厂商接收请求、手机展示通知、用户点击是三件事,不把一次接口成功当作所有手机都已收到。多团队共用安装包时,Android 点击公钥通常固定在包内,统一推送服务应使用与该公钥匹配的签名私钥;各团队无需自行更换 APP 原生配置。
第五步:点击通知后进入路线详情
使用模块九的 consumeInitialPushEvent 处理冷启动,onPushEvent 处理后续点击,两者交给同一个业务函数。收到 kind:'click' 后:
- 解析
payloadJson,确认type='route_update',且teamId / domain / routeId为有效字符串。 - 将域名与可信团队映射核对;登录未完成时暂存事件,登录和页面栈就绪后继续,不丢弃目标路线。
- 不同团队先引导用户切换并取得该团队身份;向目标团队后台查询路线详情,后台再次校验成员和路线权限。
- 后台确认可访问后,跳转自己的详情页;下面是完成前述校验后的导航片段:
// 校验后的业务 ID;在实际处理函数中用后台确认的值替换。
const teamId = 'team-a'
const routeId = 'route-001'
uni.navigateTo({
url: '/pages/route/detail?teamId=' + encodeURIComponent(teamId) +
'&routeId=' + encodeURIComponent(routeId),
fail: () => { uni.showToast({ title: '路线详情页未配置', icon: 'none' }) }
})
/pages/route/detail 是你的业务页面,需在 pages.json 登记,插件不会自动创建。403 提示无权查看,404 提示路线已下架,不自动跳转任意外部域名。推送签名通过也不代表当前登录用户仍有权限;通知已到达后再取消订阅,不会撤回旧通知,旧点击仍按当前权限处理。
“离线”指什么
| 场景 | 应怎样理解 |
|---|---|
| APP 在后台或进程已退出,手机有网络 | 配好官方通道并获通知权限后,由系统处理远程通知;仍受平台和设备策略限制 |
| 手机完全断网、关机 | 无法实时接收服务器刚发布的内容;恢复网络后是否补送取决于厂商缓存、有效期和策略 |
| Android 用户在设置中“强制停止” | 不承诺继续送达;重新打开 APP 后恢复注册和业务同步 |
| 已预先安排的本地定时提醒 | 系统按平台规则处理,与后台新发布路线的实时推送不是同一种流程 |
只调用了 onPushEvent 或点了 Mock 订阅 |
没有建立真实后台订阅关系,也不代表离线推送已接通 |
API 用途速查
| 模块 | 适用业务 | 常用方法 | 使用结果 |
|---|---|---|---|
| 能力与授权 | 接入和设置引导 | getNotificationCapabilities、getNotificationPermission、requestNotificationPermission、openNotificationSettings |
能力、授权、设置打开结果 |
| 通知条件 | 排查没有展示或定时受限 | getNotificationDiagnostics |
当前条件、阻断项与设置建议 |
| 分类 | Android 业务渠道 | createNotificationChannel、getNotificationChannel |
创建结果与系统实际配置 |
| 已显示通知 | 查看和按业务组清理 | getDeliveredNotifications、cancelNotificationGroup |
当前摘要、匹配数与取消命令提交数 |
| 即时通知 | 消息、进度、内容更新 | showNotification、updateNotification |
ID、实际样式与投递效果 |
| 系统提醒 | 一次、间隔、日历任务 | scheduleNotification、updateScheduledNotification、getScheduledNotifications |
状态、实际精度、下次时间 |
| 清理 | 单条和范围管理 | cancelNotification、cancelScheduledNotification、cancelAllNotifications |
是否影响记录、处理数量 |
| 本地通知点击 | 前台、后台、冷启动 | onNotificationClick、offNotificationClick、consumeInitialNotification |
监听令牌、业务事件 |
| 厂商推送注册 | 后台新消息 | getPushCapabilities、registerPush、getPushToken |
可用通道、真实 Token 与安装实例 |
| 远程通知点击 | 厂商消息、Token 更新、冷启动 | onPushEvent、offPushEvent、consumeInitialPushEvent |
推送事件与业务数据 |
| 团队订阅 | 路线上新、按团队通知 | 上述推送 API + 自己的业务 HTTP 接口 | 后台维护的订阅开关;插件不新增订阅 API |
核心配置
| 参数 | 类型 | 必填 | 说明 | 默认值 | 可选参数 |
|---|---|---|---|---|---|
| id | string | 否 | 业务通知 ID,1~64 位英文字母、数字、点、下划线或短横线;保存返回 ID 便于后续管理 | 自动生成 | 如 order-001 |
| title | string | 是 | 非空标题,最多 200 个 UTF-16 字符 | 无 | 业务文案 |
| body | string | 是 | 正文,最多 4000 个 UTF-16 字符,允许空字符串 | 无 | 业务文案 |
| style | string | 否 | 展示样式 | basic |
basic / big-text / big-picture / progress |
| payloadJson | string | 否 | 合法 JSON 字符串,UTF-8 不超过 8192 字节 | '{}' |
对象、数组或 JSON 基本值 |
| fallback | string | 否 | 请求的样式不可用时,报错或改用文字 | error |
error / text |
| silent | boolean | 否 | Android / iOS 请求静音;HarmonyOS 不接受单条 true,声音由系统槽位设置管理 |
false |
true / false |
| autoCancel | boolean | 否 | 点击后清除;iOS / HarmonyOS 只支持 true |
true |
Android 可设 false |
| ongoing | boolean | 否 | Android 常驻请求,不保证系统禁止清除;iOS 不支持 true |
false |
true / false |
相同 id 的 showNotification 会重新提交该通知;updateNotification 只修改已有记录中传入的字段。更新时省略的字段保持原值,false、0、空正文和空动作数组会正常生效;传入 null 不表示清空。
参数说明
样式与交互
| 参数 | 类型 | 必填 | 说明 | 默认值 | 可选参数 |
|---|---|---|---|---|---|
| bigText | string | 否 | 长文本内容,最多 8000 个字符;用于 big-text |
使用正文 | 业务文案 |
| imagePath | string | 图片样式必填 | 可读取的本地路径或平台支持的文件 URI | 无 | 不接受 HTTP URL |
| progress | NotificationProgress | 进度样式必填 | current、total 为整数,0 ≤ current ≤ total ≤ 2147483647,total ≥ 1 |
无 | indeterminate 默认 false |
| group | NotificationGroup | 否 | 必须提供业务组 id;Android 可设置 title / summary / isSummary |
无分组 | iOS 默认用 id 作为线程,可另设 ios.threadId;管理仍以业务组为准 |
| actions | NotificationAction[] | 否 | 每项 id / title 必填,ID 需唯一;标题最多 80 个字符 |
[] |
最多两个动作 |
| replaceDelivered | boolean | iOS 更新时需要 | 允许重新投递已显示通知,仅用于 updateNotification |
false |
true / false |
平台专用设置
| 参数 | 类型 | 必填 | 说明 | 默认值 | 可选参数 |
|---|---|---|---|---|---|
| android.channelId | string | 否 | 使用已创建渠道 | 插件默认渠道 | 业务渠道 ID |
| android.smallIconName | string | 否 | 应用 drawable 小图标资源名 | 插件通知图标 | 不包含扩展名 |
| android.accentColor | string | 否 | 通知强调色 | 系统默认 | #RRGGBB / #AARRGGBB |
| android.category | string | 否 | 系统通知分类 | 系统默认 | Android 合法 category 字符串 |
| android.onlyAlertOnce | boolean | 否 | 同 ID 更新时只提醒一次 | false |
true / false |
| ios.threadId | string | 否 | 显式指定通知线程 | 使用 group.id |
最多 128 个字符 |
| ios.presentInForeground | boolean | 否 | 前台是否请求显示通知 | true |
true / false |
| ios.badge | number | 否 | 应用角标,非负整数;0 表示清除 |
不主动改变 | 0~2147483647 |
| ios.categoryId | string | 否 | 保留字段;动作请通过 actions 定义 |
空 | 非空值返回不支持 |
| harmony.label | string | 否 | 保留字段,插件使用独立标签维护归属 | 空 | 非空值返回不支持 |
| harmony.slotType | number | 否 | NotificationKit 支持的通知槽类型 | 2 |
1 / 2 / 3 / 65535,仍受系统能力限制 |
| harmony.tapAbilityName | string | 否 | 点击只支持返回当前宿主 Ability | 当前宿主 Ability | 省略或与当前名称相同 |
平台专用块只在对应平台执行,不能通过其他平台字段扩展当前端的能力。
定时规则与管理
| 参数 | 类型 | 必填 | 说明 | 默认值 | 可选参数 |
|---|---|---|---|---|---|
| trigger | NotificationTrigger | 创建时是 | 单次或重复触发规则,修改时整块替换 | 无 | 下表所列四种 |
| exact | boolean | 否 | Android 请求精确闹钟;iOS/HarmonyOS 不提供这一保证 | false |
true / false |
| allowInexactFallback | boolean | 否 | Android 精确授权不足时允许使用非精确定时 | false |
true / false |
| id | string | 修改/取消时是 | 指定本插件业务 ID | 无 | 与创建结果相同 |
| scope | string | 批量取消时否 | 取消范围 | delivered |
delivered / scheduled / all |
| trigger.type | 必要字段 | 语义 |
|---|---|---|
once |
at |
未来毫秒时间戳,只提醒一次 |
interval |
intervalSeconds |
至少 60 秒的整数间隔;可选 firstAt 仅 Android |
daily |
hour、minute |
当地时间每天重复,小时 0~23,分钟 0~59 |
weekly |
hour、minute、weekdays |
当地时间按星期重复,周一为 1,周日为 7 |
修改已有任务至少传一个内容或调度字段。scheduleNotification 同 ID 重新提交与 updateScheduledNotification 的区别是:前者完整定义任务,后者保留省略的原有字段且要求记录存在。
授权、设置与渠道
| 参数 | 类型 | 必填 | 说明 | 默认值 | 可选参数 |
|---|---|---|---|---|---|
| requestBadge | boolean | 否 | iOS 授权时请求角标 | true |
true / false |
| requestSound | boolean | 否 | iOS 授权时请求声音 | true |
true / false |
| section | string | 否 | 打开的系统设置 | notification |
Android 可用 exact-alarm / channel / battery-optimization |
| channelId | string | 创建、查询或打开渠道设置时是 | 渠道唯一 ID | 无 | 与通知使用的 ID 一致 |
| channelName | string | 渠道创建时是 | 系统中可见的名称 | 无 | 业务名称 |
| channelDescription | string | 否 | 渠道用途说明 | 空 | 业务说明,仅 Android 使用 |
| importance | string | 否 | 请求的重要性 | default |
min / low / default / high / max |
| sound / vibration / showBadge | boolean | 否 | 渠道声音、震动与角标请求 | true |
true / false |
通知检查与当前通知管理
| 参数 | 适用方法 | 默认值与使用方式 |
|---|---|---|
| purpose | getNotificationDiagnostics |
immediate;检查定时提醒用 scheduled |
| exact | getNotificationDiagnostics |
false;Android 的定时检查设为 true 才检查精确闹钟条件 |
| channelId | 诊断、渠道查询、设置 | 1~64 位英文、数字、点、下划线或连字符;查询渠道及 section: 'channel' 必填 |
| harmonySlotType | getNotificationDiagnostics |
省略时使用默认业务槽位;可选 1 / 2 / 3 / 65535 |
| groupId | 列表、按组清理 | 同 group.id 的格式;列表可省略查看全部,清理必须非空 |
| section | openNotificationSettings |
notification;Android 可选 exact-alarm / channel / battery-optimization |
诊断的 checks 每项包含 id / state / blocking / message / action。state 可为 enabled / disabled / not-required / unsupported / unknown;设置建议 action 为 none / notification-settings / channel-settings / exact-alarm-settings / battery-settings,按平台和用户操作选择对应入口。
回调说明
异步 API 接收 success / fail / complete。一次调用最终只进入一个成功或失败分支,随后调用 complete;complete 为统一结果 { operation, success, notificationId, errCode?, errMsg }。页面回调抛出异常不会再次触发成功或失败分支。
onNotificationClick(callback) 是持续监听,返回 listenerId;offNotificationClick(listenerId) 仅移除该监听并返回是否移除,页面销毁时必须执行。多个订阅者各自接收事件,不要在每次页面 onShow 重复注册。
| 点击事件字段 | 含义 |
|---|---|
| eventId | 本次事件 ID,可用于业务去重 |
| notificationId | 创建通知时的业务 ID |
| actionId | 动作 ID;点击通知主体时为空 |
| payloadJson | 主体或对应动作的 JSON 数据 |
| source | notification / action / scheduled-reminder |
| timestamp | 捕获事件时的毫秒时间戳 |
| coldStart | 事件是否在应用冷启动捕获窗口内收到 |
支持平台
| 能力 | Android | iOS | HarmonyOS |
|---|---|---|---|
| 最低系统 | Android 5.0 | iOS 12 | 以项目 HarmonyOS SDK 和能力支持为准 |
| 普通、长文本 | 支持 | 支持,长文本使用正文 | 支持 |
| 本地图片 | 支持 | 系统图片附件 | 支持,受资源可读性约束 |
| 进度 | 原生进度条 | 显式选择文字替代 | 查询系统进度模板后使用 |
| 分组、两个前台动作 | 支持 | 线程分组、前台动作 | 支持即时通知 |
| 更新已显示通知 | 同 ID 更新 | 需 replaceDelivered: true,重新投递 |
API 18 及以上同 ID 更新,低版本明确不支持 |
| 一次、每日、每周 | 系统闹钟调度 | 系统通知调度 | API 12 及以上系统代理提醒,仅基础文字,需权限与权益 |
| 间隔重复 | 至少 60 秒 | 至少 60 秒,不支持 firstAt |
不支持 |
| 常驻、点击后保留 | 支持 ongoing / autoCancel |
不支持常驻或 autoCancel: false |
即时通知支持常驻,不支持 autoCancel: false |
| 精确定时请求 | 需系统授权,仍受系统约束 | 不支持 exact: true |
不支持 exact: true |
| 即时通知点击业务数据 | 支持 | 支持 | 支持 |
| 定时提醒点击数据 | 支持 | 支持 | 不支持,系统提醒只返回应用;传入业务数据或动作会报错 |
| Android 渠道 API | 支持 | 返回不支持 | 返回不支持 |
| 只读通知条件检查 | 应用、渠道及按用途检查定时条件 | 授权、提醒、声音、角标等系统设置 | 应用、业务槽位和代理提醒条件 |
| 实际渠道查询 / 渠道设置 | Android 8 及以上 | 返回不支持 | 返回不支持 |
| 电池优化设置 | Android 6 及以上系统列表 | 返回不支持 | 返回不支持 |
| 已显示通知查询 / 按组清理 | Android 6 及以上,本插件本地通知 | iOS 12 及以上,本插件本地通知 | API 12 及以上,本插件即时本地通知 |
| 官方远程推送 | 华为/荣耀/小米/OPPO/vivo/魅族/FCM,按设备与配置选择 | APNs alert | Push Kit 普通通知 |
| 团队业务订阅 | 配合自有后台 | 配合自有后台 | 配合自有后台 |
适用宿主为 uni-app 和 uni-app x;Web、小程序不提供系统通知实现,调用相关操作返回 9082004。通知展示需系统授权;Android 精确定时和 HarmonyOS 代理提醒还需满足各自的系统前提。
返回值说明
| 结果 | 主要字段与含义 |
|---|---|
| 通知提交 | id / platform / accepted / effectiveStyle / deliveryEffect / warnings;受理不等于已弹出横幅 |
| 定时提交 | id / nativeId / triggerType / state / precision / nextTriggerAt / warnings;nativeId 只作诊断,不作为后续 API 的业务 ID |
| 定时查询 | items 中包含 id / nativeId / triggerType / state / precision / nextTriggerAt / systemConfirmed / warning |
| 单条取消 | affected 表示本次是否影响记录;已显示通知还有 deliveryEffect,定时任务还有 previousState |
| 批量取消 | scope / deliveredCount / scheduledCount;Android / iOS 按业务 ID 计数,一条多星期提醒算一个任务 |
| 授权查询 | notification / exactAlarm / agentReminder / canPost / canSchedule,并包含 platform |
| 能力查询 | platform / osVersion / capabilities / limits;每项能力含 state / reason |
| 渠道创建 | channelId / created / importance / settingsMutable / warnings,并包含 platform |
| 打开设置 | platform / section / opened;返回后应重新查询授权 |
| 通知条件检查 | platform / purpose / checkedAt / checks;无法确认的条件保留 unknown |
| 实际渠道查询 | channelId / exists / enabled / importance / sound / vibration / showBadge;importance 另包含 none / unknown |
| 已显示通知查询 | items 中包含 id / groupId / title / body / postedAt;另有 observedAt / warnings |
| 按业务组清理 | groupId / matchedCount / submittedCount / failedIds / warnings;按业务 ID 计数,仅表示取消命令提交情况 |
deliveryEffect 区分 posted(提交展示)、reposted(重新投递)、updated(更新)、cancelled(取消)和 unchanged(没有变化)。定时 state 为 submitting / scheduled / expired / cancelled / invalid / unknown;precision 为 exact / inexact / system-calendar / unknown。
查询里的 nextTriggerAt 为预计下次毫秒时间戳,无法确认时可为 0。Android 无法可靠查询系统闹钟是否仍存在,因此 systemConfirmed: false 不代表任务必然丢失;应用内登记也不代表系统保证送达。iOS 每周多个星期会占用多个系统待触发请求,配额与应用其他通知共享。
limits 包含动作数、payload 字节、图片字节、点击缓存数、最小重复间隔和任务上限。以当前设备查询结果及实际调用为准,超过配额通过失败回调返回。
错误码说明
| 错误码 | 含义 | 处理建议 |
|---|---|---|
| 9082001 | 参数不合法 | 核对 ID、时间、JSON、进度和字段类型 |
| 9082002 | 未获得通知授权 | 在用户操作时申请授权,必要时引导系统设置 |
| 9082003 | 应用通知或渠道被关闭 | 检查系统通知和业务渠道设置 |
| 9082004 | 当前能力不支持 | 查询平台能力,选择可用功能 |
| 9082005 | 无法原样展示请求的样式 | 调整样式或显式设置 fallback: 'text' |
| 9082006 | Android 精确定时授权不可用 | 引导精确定时设置,或允许非精确替代 |
| 9082007 | HarmonyOS 代理提醒前提不满足 | 检查应用提醒权限、权益和签名配置 |
| 9082008 | 本地资源不可读取 | 检查图片路径、授权、大小和格式 |
| 9082009 | 要修改的通知或任务不存在 | 先创建,使用返回的同一业务 ID |
| 9082010 | 超过通知、动作或提醒配额 | 减少动作或清理不再使用的任务 |
| 9082011 | 原生操作失败 | 查看 nativeCode / details,处理后重试 |
| 9082012 | 更新、恢复或回滚未完整完成 | 重新查询任务状态,再明确取消或重建 |
| 9082013 | 厂商或签名配置缺失 | 按模块九核对原生包、厂商账号和签名配置 |
| 9082014 | 尚未取得有效推送 Token | 先注册,再等待成功/Token 事件;处理网络或配置问题后重试 |
失败对象统一包含 errSubject / errCode / errMsg / operation / platform / nativeCode / recoverable / notificationId / details。recoverable 只提示处理条件后可以重试,不代表应当立即循环重试。
常见问题
通知权限已允许,为什么订阅后还是收不到?
依次检查:是否取得真实 Token、后台是否保存了当前用户和团队绑定、订阅是否开启、后台是否实际向对应厂商发送通知栏消息。Mock 开关不会影响真实后台;透传消息也不等同于系统通知栏消息。
onNotificationClick 和 onPushEvent 用哪个?
本地通知使用前者,厂商远程通知使用后者;冷启动分别使用 consumeInitialNotification 和 consumeInitialPushEvent。页面销毁时释放自己创建的监听,避免重复注册。
一个团队一个域名,需要每个团队再打一个 APP 吗?
同一个安装包可以由业务层切换团队后台,团队域名不是厂商应用身份。厂商账号仍对应安装包的包名、签名和配置;推荐后台按团队隔离设备与订阅,由统一发送服务管理同一 APP 的推送配置。
取消订阅后,通知栏旧消息怎么还在?
取消订阅阻止后续业务发送,已经发出的通知不会自动撤回。offPushEvent 仅关闭当前页面监听,也不能替代后台取消订阅。
只更新文档或示例,需要重打基座吗?
已有匹配原生包时,通常更新页面资源即可。首次接入或更新原生代码、SDK、权限和厂商配置后,需要重新制作并安装对应平台原生包。
注意事项
- 使用包含本插件原生代码的安装包;首次接入或原生代码更新后,应重新制作并安装 Android 自定义基座,并重新打包 iOS / HarmonyOS。
- 应用必须拥有发送通知所需的系统授权。勿扰、专注、静音、渠道设置和厂商省电策略都可能影响声音、横幅和时间,插件不保证绕过系统设置。
- 系统定时任务无需页面定时器,但强制停止、卸载、数据清除或系统限制可能使任务失效。Android 普通前台恢复会保留仍在等待系统投递的提醒,不因计划时间已过就取消;重启、系统时间/时区改变等重建场景仍只安排未来任务,已错过的单次提醒不补发,重复任务跳到下一次。未完成的系统恢复在成功注册持久任务后由系统继续处理,仍受后台调度约束,不保证立即执行。注册临时失败会在广播期限内最多尝试三次;系统持续拒绝时保留队列并记录告警,等待下次前台或系统事件重试。重新进入应用后可查询并按业务规则重新安排。
cancelNotification处理已显示通知,cancelScheduledNotification停止未来提醒;如果两者都需要清理,分别取消或使用scope: 'all'。HarmonyOS 的已显示代理提醒由系统管理,清理已显示范围只处理插件的即时通知;停止未来提醒使用调度取消 API。- 本地通知的
imagePath只传本地可读图片,较大图片建议先压缩;iOS 服务端图片推送另按模块九接入通知服务扩展。Android 使用小图标资源时应提供适合状态栏的单色图形。不要把业务敏感信息直接放进锁屏通知、payload 或页面日志。 - 插件只在设备本地保存通知管理和点击所需数据,不向作者服务器发送内容。应用开发者仍需在自身隐私政策中说明实际业务的数据使用方式。
第三方依赖说明见 THIRD_PARTY_NOTICES.md。
联系方式
信-微:l-z-1-8-7-1512-5421(-去掉,不这样写会被和谐)
作者系列 UTS 插件
以下为已在 DCloud 插件市场上架的作者系列 UTS 插件,可按业务场景组合使用。未列出的插件表示当前未确认公开市场页,后续上架后再补充。
| 插件 | 能力方向 | 插件市场 |
|---|---|---|
lizhao-nfc-pro |
NFC 标签读写、NDEF、IsoDep 与诊断 | 查看插件 |
lizhao-float-window |
悬浮窗、画中画、权限与诊断 | 查看插件 |
lizhao-device-id |
设备标识、隐私策略与诊断 | 查看插件 |
lizhao-scan-pro |
原生扫码、连续扫码、相册识别 | 查看插件 |
lizhao-choose-file |
原生文件选择、上传、进度与取消 | 查看插件 |
lizhao-bg-audio |
背景音频播放、队列、倍速与事件 | 查看插件 |
lizhao-smart-tts |
系统 TTS、云端合成、听书方案 | 查看插件 |
lizhao-share-plus |
系统分享、远程文件下载后分享 | 查看插件 |
lizhao-sqlite-pro |
原生 SQLite、迁移、备份与诊断 | 查看插件 |
lizhao-icon-pro |
SVG 图标组件、多主题与缓存 | 查看插件 |
lizhao-cast-screen |
DLNA 投屏、AirPlay 路由入口 | 查看插件 |
lizhao-call-kit |
电话、短信、通讯录原生能力 | 查看插件 |
lizhao-app-keepalive |
应用保活、唤醒、自愈与报告 | 查看插件 |
lizhao-doc-corrector |
文档扫描、矫正、增强与识别 | 查看插件 |
lizhao-emu-detect |
模拟器环境检测、风险评分与证据 | 查看插件 |
lizhao-gallery-pro |
相册媒体分页、筛选、缩略图与导出 | 查看插件 |
lizhao-video-thumb |
视频封面、批量取帧与 Base64 返回 | 查看插件 |
lizhao-ble |
BLE 扫描、连接、读写、通知与自动重连 | 查看插件 |
lizhao-sse-pro |
SSE、Line、JSONL 与 Raw 流式请求 | 查看插件 |
lizhao-pdf-pro |
PDF 阅读、签批、真实写回与页面处理 | 查看插件 |
lizhao-serial-port |
路径串口、USB 串口、多会话收发与诊断 | 查看插件 |
lizhao-wechat-kit |
微信登录、分享、支付、小程序与客服 | 查看插件 |
lizhao-video-editor |
视频裁剪、压缩、取帧与 FFmpeg/FFprobe | 查看插件 |
lizhao-vpn-pro |
企业 VPN、IKEv2、安全接入与脱敏诊断 | 查看插件 |
lizhao-camera-pro |
原生相机、拍照录像、水印与媒体保存 | 查看插件 |
lizhao-tcp-pro |
TCP 客户端、服务端、多连接与诊断 | 查看插件 |
lizhao-notify-pro |
本地通知、点击动作、进度与定时提醒 | 查看插件 |

收藏人数:
购买源码授权版(
试用
赞赏(0)
下载 6486
赞赏 5
下载 12735115
赞赏 1959
赞赏
京公网安备:11010802035340号