更新记录

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 只在应用有执行机会时发本地通知,不能代替服务端推送。

按这个顺序接入:

  1. 在下表对应的官方平台创建应用,完成包名、签名和客户端配置;使用已包含这些配置的安装包。
  2. 用户同意隐私政策后,点按钮申请通知权限并调用 registerPush。
  3. 将返回的 Token 和通道上报自己的 HTTPS 后台;Token 更新时重新上报。
  4. 后台向该设备发送一条通知栏消息,分别检查通知展示和点击回调。团队订阅继续看模块十。
平台 官方客户端 使用条件 进程退出后系统通知
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 的 `` 可配置下列字段。ID 等数字值使用字符串资源保存,避免被 Android 当成数值或资源编号。vivo 的配置必须进入原生包,运行时传参不能替代它;若传入不同值则拒绝注册。 | 通道 | 宿主 Manifest 元数据 | 说明 | | --- | --- | --- | | 小米 | `lizhao.notify.push.xiaomi.app_id`、`lizhao.notify.push.xiaomi.app_key` | 或使用 registerPush 的 appId / appKey | | OPPO | `lizhao.notify.push.oppo.app_key`、`lizhao.notify.push.oppo.app_secret` | 或使用 appKey / oppoAppSecret | | vivo | `com.vivo.push.app_id`、`com.vivo.push.api_key` | 官方也支持短名 app_id / api_key;建议使用厂商前缀,避免冲突;运行需要 Android 6.0+ | | 魅族 | `lizhao.notify.push.meizu.app_id`、`lizhao.notify.push.meizu.app_key` | 或使用 appId / appKey;服务端使用通知栏消息,普通透传已停用 | | 华为 | `com.huawei.hms.client.appid` | 或使用 appId;需启用 HMS Push Kit | | 荣耀 | `com.hihonor.push.app_id` | 必须配置到原生包中 | ##### 华为、荣耀与签名公钥 宿主需分别在[华为开发者后台](https://developer.huawei.com/consumer/en/codelab/HMSPushKit/index.html%230)或[荣耀 Push Kit 后台](https://developer.honor.com/cn/docs/11002/guides/intergrate)创建应用,确保包名与签名一致。华为调用 `registerPush({ provider: 'huawei', appId: 'AGC 应用 App ID' })`;荣耀须在宿主 `AndroidManifest.xml` 覆盖插件的空 `com.hihonor.push.app_id` 元数据。宿主 Manifest 的根 `` 声明 `xmlns:tools="http://schemas.android.com/tools"`,在 `` 内配置下列节点;将公钥替换为业务服务端私钥对应的真实值: ```xml <meta-data android:name="com.hihonor.push.app_id" android:value="你的荣耀 App ID" tools:replace="android:value" /> <meta-data android:name="lizhao.notify.push.click_public_key" android:value="Base64 编码的 RSA SPKI 公钥" tools:replace="android:value" /> ``` 缺厂商配置返回 `9082013`;缺点击公钥时注册仍可完成,但点击只打开应用,不派发业务事件。厂商服务端发送密钥、FCM 服务账号私钥和 RSA 签名私钥不能放到客户端。升级本版后,**必须重新制作并安装 Android 自定义基座**,再更新页面资源。 ##### FCM 配置 FCM 需要设备上的 Google Play 服务及可访问 Google 服务的网络。在 Firebase 后台登记实际 Android 包名,将该应用 `google-services.json` 中的客户端值映射到宿主 Android 原生资源 `res/values/firebase.xml`(uni-app/uni-app x 的原生资源目录按 [DCloud Android 资源配置](https://uniapp.dcloud.net.cn/tutorial/app-nativeresource-android.html)设置): ```xml YOUR_FIREBASE_MOBILESDK_APP_ID YOUR_FIREBASE_CLIENT_API_KEY YOUR_FIREBASE_PROJECT_NUMBER YOUR_FIREBASE_PROJECT_ID ``` 也可使用宿主已有的 Firebase 配置,避免重复声明资源。无需为不使用 FCM 的宿主启用 Google Services Gradle 插件。插件默认关闭 FCM 自动注册及 Analytics 收集,显式调用 `registerPush({ provider: 'fcm', success, fail })` 后才启动 Token 注册;应用应在用户同意后调用。[Firebase 官方接入说明](https://firebase.google.com/docs/cloud-messaging/android/get-started) ##### Android 通知点击 所有 Android 通道共用下方签名协议。服务端将点击目标设为 `uts.sdk.modules.lizhaoNotifyPro.PushClickActivity`,动作名按通道选择: | provider | 自定义点击 action | | --- | --- | | xiaomi | `uts.sdk.modules.lizhaoNotifyPro.PUSH_XIAOMI_CLICK` | | huawei | `uts.sdk.modules.lizhaoNotifyPro.PUSH_HUAWEI_CLICK` | | honor | `uts.sdk.modules.lizhaoNotifyPro.PUSH_HONOR_CLICK` | | oppo | `uts.sdk.modules.lizhaoNotifyPro.PUSH_OPPO_CLICK` | | vivo | `uts.sdk.modules.lizhaoNotifyPro.PUSH_VIVO_CLICK` | | meizu | `uts.sdk.modules.lizhaoNotifyPro.PUSH_MEIZU_CLICK` | | fcm | `uts.sdk.modules.lizhaoNotifyPro.PUSH_FCM_CLICK` | vivo 新通知使用服务端 Activity Intent 路由;魅族 Android 12+ 不使用已不支持的 clickType=3 自定义方式,应配置 Activity 点击。FCM 使用 `android.notification.click_action` 和 `data` 中的签名字段。前台消息与通知栏展示遵循各官方 SDK 的规则,不会把透传消息自动转成本地通知。魅族普通透传已停用;vivo 的数据回调限厂商允许的特定 VoIP 场景,普通通知不承诺 `kind:'message'`;OPPO 透传需要厂商开通对应权限,注册成功不代表自动获得透传资格。 华为/荣耀通知点击的服务端 `clickAction` 应指向插件注册的专用 Activity。华为自定义点击 action 为 `uts.sdk.modules.lizhaoNotifyPro.PUSH_HUAWEI_CLICK`,荣耀为 `uts.sdk.modules.lizhaoNotifyPro.PUSH_HONOR_CLICK`;华为带业务参数时优先用官方自定义 Intent URI,荣耀按官方 `clickAction` 的 action/data 传参。服务端字段位置随厂商发送 API 版本变化,发布前应以[华为通知点击文档](https://developer.huawei.com/consumer/de/doc/HMSCore-Guides/android-cond-send-0000001050040128)与[荣耀通知行为文档](https://developer.honor.com/cn/docs/11002/guides/notification-action)核对请求。推送内容从自己的服务端发送,不把厂商 REST 凭据嵌进插件。 **Android 业务点击默认要求服务端签名。** 厂商点击 Activity 必须 `exported=true` 才能由厂商跨应用启动,所以 action/extras 本身不能证明消息来源。宿主在 Manifest `` 中配置 `lizhao.notify.push.click_public_key`,值为 Base64 编码的 RSA SubjectPublicKeyInfo 公钥(至少 2048 位);私钥只放业务服务端。`registerPush` / `getPushToken` 返回的 `installationId` 与 Token 一并上报。服务端用 SHA256withRSA 签署以下原文的 UTF-8 字节,换行符固定为 `\n`,不得重排 JSON 字符串或更换空白: ```text lizhao-notify-pro.click.v1\n\n\n\n\n\n ``` 点击 Intent 必须携带 `lizhaoPushEventId`、`lizhaoPushPayload`(最多 8192 字节的有效 JSON)、`lizhaoPushInstallationId`、`lizhaoPushExpiresAt`(13 位 Unix 毫秒时间,不超过当前时间 7 天)和 `lizhaoPushSignature`(标准 Base64);VIEW 路由还须带 `lizhaoPushProvider`。下例展示发送前应生成的 Intent 数据;`signatureBase64` 必须由服务端对上方原文签署,不能在客户端计算: ```kotlin val click = Intent("uts.sdk.modules.lizhaoNotifyPro.PUSH_HONOR_CLICK") click.setClassName(applicationId, "uts.sdk.modules.lizhaoNotifyPro.PushClickActivity") click.putExtra("lizhaoPushEventId", eventId) click.putExtra("lizhaoPushPayload", payloadJson) click.putExtra("lizhaoPushInstallationId", installationId) click.putExtra("lizhaoPushExpiresAt", expiresAt.toString()) click.putExtra("lizhaoPushSignature", signatureBase64) val clickIntentUri = click.toUri(Intent.URI_INTENT_SCHEME) ``` 华为把 action 改为 `PUSH_HUAWEI_CLICK`;如使用 VIEW 路由,URI 为 `lizhao-notify:///push`,Intent 还需带 `lizhaoPushProvider`。服务端通过厂商接口提交适配该厂商版本的 `clickAction` / Intent URI。**只配置 action 或普通 `message.data`,不足以形成业务点击事件。**公钥缺失、签名无效、过期或安装实例不匹配时,只打开 App,不生成 `kind:'click'` 事件。生成 Intent URI 时请用 Android `Intent.toUri(Intent.URI_INTENT_SCHEME)` 或等价安全编码工具,不能直接拼接带 JSON 的 URI。页面收到验签通过的事件仍应核验登录态与业务 ID。

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”:

  1. 查看当前演示团队和域名,点击“模拟绑定设备”。
  2. 点击“订阅路线上新”,观察模块内状态变为“已订阅”。
  3. 点击“模拟发布路线”,生成一条本页演示通知。
  4. 点击“预览通知点击”,在模块内查看路线详情预览。
  5. 点击“取消订阅”,再模拟发布,当前用户不再产生新提醒;已有提醒不会被撤回。
  6. 切换到另一个演示团队后,重新绑定、订阅;直接点击上一团队的通知会提示先切换并核验权限。

此卡片使用内存 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({ url: apiBase + path, method: 'PUT', data: data, header: { Authorization: 'Bearer ' + accessToken, 'Content-Type': 'application/json' }, success: (res) => { const body = res.data if (res.statusCode == 200 && body != null && body.getNumber('code') == 0) { done(body) } else { uni.showToast({ title: '后台未保存,请检查登录或权限', icon: 'none' }) } }, fail: () => { uni.showToast({ title: '网络异常,未保存,请重试', icon: 'none' }) } }) } function bindTeamDevice(device: PushTokenResult): void { putTeamSetting('/api/push/devices', { teamId: teamId, provider: device.provider, platform: device.platform, token: device.token, installationId: device.installationId ?? '', bindingId: bindingId }, (body: UTSJSONObject) => { const nextBindingId = body.getJSON('data')?.getString('bindingId') ?? '' if (nextBindingId.length == 0) { uni.showToast({ title: '后台未返回设备绑定编号', icon: 'none' }) return } bindingId = nextBindingId uni.setStorageSync(bindingCacheKey, bindingId) uni.showToast({ title: '设备已绑定,可选择订阅', icon: 'none' }) }) } // 用户同意隐私政策并登录后,由按钮触发。 function enableTeamPush(): void { if (accessToken.length == 0) { uni.showToast({ title: '请先登录当前团队', icon: 'none' }) return } requestNotificationPermission({ success: (permission: NotificationPermissionResult) => { if (!permission.canPost) { uni.showToast({ title: '请在系统设置允许通知', icon: 'none' }) return } registerPush({ success: bindTeamDevice, fail: (err: NotificationFail) => { uni.showToast({ title: '注册失败:' + err.errCode, icon: 'none' }) } }) }, fail: () => { uni.showToast({ title: '通知授权未完成', icon: 'none' }) } }) } // 请求期间禁用按钮;绑定成功后由订阅/取消按钮传入 true/false。 function setRouteSubscription(enabled: boolean): void { putTeamSetting('/api/subscriptions/route-update', { teamId: teamId, topic: 'route_update', enabled: enabled }, () => { subscribed = enabled uni.showToast({ title: enabled ? '已订阅路线上新' : '已取消订阅', icon: 'none' }) }) } ```

上面是单次接入片段,生产页面还需接好这几个生命周期:

  • 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' 后:

  1. 解析 payloadJson,确认 type='route_update',且 teamId / domain / routeId 为有效字符串。
  2. 将域名与可信团队映射核对;登录未完成时暂存事件,登录和页面栈就绪后继续,不丢弃目标路线。
  3. 不同团队先引导用户切换并取得该团队身份;向目标团队后台查询路线详情,后台再次校验成员和路线权限。
  4. 后台确认可访问后,跳转自己的详情页;下面是完成前述校验后的导航片段:
// 校验后的业务 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、权限和厂商配置后,需要重新制作并安装对应平台原生包。

注意事项

  1. 使用包含本插件原生代码的安装包;首次接入或原生代码更新后,应重新制作并安装 Android 自定义基座,并重新打包 iOS / HarmonyOS。
  2. 应用必须拥有发送通知所需的系统授权。勿扰、专注、静音、渠道设置和厂商省电策略都可能影响声音、横幅和时间,插件不保证绕过系统设置。
  3. 系统定时任务无需页面定时器,但强制停止、卸载、数据清除或系统限制可能使任务失效。Android 普通前台恢复会保留仍在等待系统投递的提醒,不因计划时间已过就取消;重启、系统时间/时区改变等重建场景仍只安排未来任务,已错过的单次提醒不补发,重复任务跳到下一次。未完成的系统恢复在成功注册持久任务后由系统继续处理,仍受后台调度约束,不保证立即执行。注册临时失败会在广播期限内最多尝试三次;系统持续拒绝时保留队列并记录告警,等待下次前台或系统事件重试。重新进入应用后可查询并按业务规则重新安排。
  4. cancelNotification 处理已显示通知,cancelScheduledNotification 停止未来提醒;如果两者都需要清理,分别取消或使用 scope: 'all'。HarmonyOS 的已显示代理提醒由系统管理,清理已显示范围只处理插件的即时通知;停止未来提醒使用调度取消 API。
  5. 本地通知的 imagePath 只传本地可读图片,较大图片建议先压缩;iOS 服务端图片推送另按模块九接入通知服务扩展。Android 使用小图标资源时应提供适合状态栏的单色图形。不要把业务敏感信息直接放进锁屏通知、payload 或页面日志。
  6. 插件只在设备本地保存通知管理和点击所需数据,不向作者服务器发送内容。应用开发者仍需在自身隐私政策中说明实际业务的数据使用方式。

第三方依赖说明见 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 本地通知、点击动作、进度与定时提醒 查看插件

隐私、权限声明

1. 本插件需要申请的系统权限列表:

Android 按功能使用通知、震动、精确定时及对应厂商推送 SDK;iOS 使用系统通知授权和 Push Notifications 签名能力;HarmonyOS 使用通知授权和已开通的 Push Kit,系统托管提醒另需对应权益。

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

通知内容、图片路径和业务透传数据用于设备通知;厂商 SDK 向对应官方服务传输注册所需的应用及设备信息,具体范围见各 SDK 隐私说明。Token 与点击参数保存在设备并交给页面回调,插件不向作者服务器上传。业务方应在用户同意后注册,并将 Token 上报自己的服务端。

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

无