更新记录
1.0.0(2026-10-28)
首个版本。按插件市场《应用消息通知插件(多种样式,新增支持常驻通知模式)Ba-Notify》的参数表与回调字段 1:1 复刻,并把只支持 Android 的能力扩到 Android + iOS 双端,全源码交付。
- 七种样式 notifyType:0 普通 / 1 大图 / 2 按钮 / 3 HeadUp / 4 消息盒子 / 5 多行 / 6 进度。
- 常驻通知 ongoing:true 在 Android 8+ 同时下 FLAG_ONGOING_EVENT 与 FLAG_NO_CLEAR,侧滑删不掉。
- 渠道与 ID 分类管理:clear() 清全部、clearById({ID}) 清单条;同 ID 再次 show() 刷新同一条通知。
- 权限:isNotifyEnabled() 查询、goSetNotify() 跳系统设置、requestNotifyPermission() 申请 Android 13+ 的 POST_NOTIFICATIONS 与 iOS 通知授权。
- 点击回传字段与原插件一致:BaNotifyChannelID / BaNotifyChannelName / BaNotifyID / notifyType / extend,点按钮额外带 Notify-Click(leftBtn / rightBtn)。
- Android 走 plus.runtime.arguments + plus.globalEvent(newintent);iOS 走 onClick() / getLastClick() / clearLastClick(),并在 applicationDidFinishLaunching 前装好通知代理,冷启动点击不丢。
- iOS 差异已明确降级并写进文档:进度条转文字进度条、消息盒子转多行正文、渠道转 threadIdentifier 归组;ongoing / autoCancel / ticker / isVibrate / isLights / smallIcon 在 iOS 无对应能力。
- 空值容错:UTS 可选属性未赋值会序列化成 null,双端内核统一回落默认值,不会把 "null" 显示到通知上。
- 已实测 Android 13(API 33)、Android 16(API 36),覆盖七种样式、常驻、模糊进度、静音渠道、单条清除、全清、权限查询、跳设置、正文点击与按钮点击回传;iOS 侧完成类型检查与 51 项参数/点击回传逻辑回归。
平台兼容性
uni-app(4.25)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| √ | √ | × | × | √ | - | 5.0 | 12 | × |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| × | × | × | × | × | × | × | × | × | × | × | × |
zeng-notify · 应用消息通知(多种样式 + 常驻通知,Android / iOS 双端)
参数、方法名、点击回传字段与「应用消息通知插件(多种样式,新增支持常驻通知模式)Ba-Notify」逐一对齐, 原来只支持 Android,这份把 iOS 也补齐了,而且是全源码交付(Java 内核 + Swift 内核 + UTS 封装层都在包里,无混淆、无加密)。
迁移时只要把这一行换掉,其余代码不用动:
// 旧
const notify = uni.requireNativePlugin('Ba-Notify')
// 新
import { notify } from '@/uni_modules/zeng-notify'
平台兼容性
| 平台 | 支持 | 最低版本 | 说明 |
|---|---|---|---|
| Android | ✅ | API 21(Android 5.0) | 七种样式全部真机实测 |
| iOS | ✅ | iOS 10 | 用 UNUserNotificationCenter 本地通知,样式差异见「iOS 与 Android 的差异」 |
| HarmonyOS | ❌ | - | 未实现 |
| H5 / 小程序 | ❌ | - | 系统通知栏能力,Web 侧没有 |
已实测环境:Android 13(API 33)与 Android 16(API 36)模拟器,覆盖七种样式、常驻、模糊进度、静音渠道、clearById、clear、isNotifyEnabled、goSetNotify、按钮点击与正文点击的参数回传。
iOS 侧已完成的验证:ZengNotifyNative.swift 通过 Swift 类型检查,并有 51 项参数解析与点击回传字段的逻辑回归全部通过。作者环境没有可用来跑画面的 iOS 真机,因此 iOS 的画面效果请以你自己在 HBuilderX 自定义基座上的运行为准;若与文档不符,欢迎在插件详情页反馈,作者会跟进。
快速开始
- 把
uni_modules/zeng-notify整个目录拷进你项目的uni_modules/下。 - HBuilderX 里 运行 → 运行到手机或模拟器 → 制作自定义调试基座(UTS 插件必须自定义基座,标准基座里没有我们的原生代码)。
- 运行到真机后把右上角基座切成「自定义调试基座」。手机上装过旧基座先卸载,否则签名冲突。
- Android 13+ 需要先申请通知权限,iOS 首次
show()会自动弹授权。
import { notify } from '@/uni_modules/zeng-notify'
// Android 13+ 申请 POST_NOTIFICATIONS;iOS 直接弹系统授权
notify.requestNotifyPermission((res) => {
console.log('已发起授权', res)
})
notify.isNotifyEnabled((res) => {
if (!res.isNotifyEnabled) {
uni.showModal({
title: '通知未开启',
content: '请到系统设置里打开通知',
success: (r) => { if (r.confirm) notify.goSetNotify() }
})
}
})
方法
| 方法 | 说明 | Android | iOS |
|---|---|---|---|
show(options, callback?) |
显示通知,回调 { code, ID, channelID, channelName, notifyType, message } |
✅ | ✅ |
isNotifyEnabled(callback) |
查询通知权限,回调 { code, isNotifyEnabled, ... } |
✅ | ✅ |
goSetNotify() |
跳系统通知设置页 | ✅(直达本应用通知页) | ✅(只能到本应用设置页,通知开关在该页内) |
clear() |
清空本应用全部通知 | ✅ | ✅(同时清掉待推送) |
clearById({ ID }) |
按通知 ID 清除单条 | ✅ | ✅ |
requestNotifyPermission(callback?) |
主动申请权限 | ✅(API 33+ 弹系统框) | ✅(requestAuthorization) |
getLastClick() |
读最近一次点击参数,没有返回 null |
✅ | ✅ |
clearLastClick() |
清掉缓存的点击参数 | 空实现(Android 参数挂在启动 Intent 上,不落地缓存) | ✅ |
onClick(callback) |
接收点击 / 按钮事件 | 见下方说明 | ✅ |
Android 的点击事件和原插件一样走
plus.runtime.arguments+plus.globalEvent('newintent'), 因为 uni-app 的安卓容器就是这样把参数交给页面的;onClick()在 Android 只保留同名方法(会打一条 warn), 方便一份页面代码在双端跑。iOS 没有 plus 的 newintent 通道,用onClick()。
show() 参数
notifyType 决定样式:0 普通、1 大图、2 按钮、3 HeadUp、4 消息盒子、5 多行、6 进度。
| 字段 | 类型 | 默认 | 说明 | Android | iOS |
|---|---|---|---|---|---|
notifyType |
number | 0 |
样式类型 | ✅ | ✅ |
channelID |
string | "1" |
渠道 id,同 id 复用同一渠道 | ✅ | 归组用(threadIdentifier) |
channelName |
string | "默认" |
渠道显示名 | ✅ | 仅记录在点击参数里 |
ID |
number | 0 |
通知 id,同 id 再次 show 会刷新同一条 |
✅ | ✅ |
isSound |
boolean | true |
是否有声音 | ✅ | ✅ |
isVibrate |
boolean | true |
是否震动 | ✅ | ❌ 系统不支持单独控制 |
isLights |
boolean | true |
是否呼吸灯 | ✅ | ❌ 无呼吸灯 |
ticker |
string | "" |
状态栏滚动提示文字 | ✅ | ❌ iOS 无 ticker |
title |
string | "" |
标题 | ✅ | ✅ |
content |
string | "" |
内容,多行可用 \n |
✅ | ✅ |
thumbUrl |
string | "" |
缩略图本地绝对路径 | ✅ | ✅ 作为附件 |
bigUrl |
string | "" |
大图本地绝对路径 | ✅ | ✅ 作为附件 |
leftBtnText |
string | "" |
左按钮文字 | ✅ | ✅(长按/下拉出动作) |
rightBtnText |
string | "" |
右按钮文字 | ✅ | ✅(同上) |
msgList |
string[] | [] |
消息盒子每行文字 | ✅ 最多 7 行 | ✅ 拼进正文,最多 5 行 |
maxProgress |
number | 100 |
进度最大值 | ✅ | ✅(换算成百分比) |
progress |
number | 0 |
当前进度 | ✅ | ✅(文字进度条) |
indeterminate |
boolean | false |
模糊进度(不显示百分比) | ✅ | ✅(显示「处理中」) |
finishText |
string | "" |
进度跑满后的文案 | ✅ | ✅ |
autoCancel |
boolean | true |
点击后自动消失 | ✅ | ❌ iOS 点击必消失,无法保留 |
ongoing |
boolean | false |
常驻通知(侧滑不可删) | ✅ | ❌ iOS 无常驻概念 |
extend |
string | "" |
附加参数,原样出现在点击参数里 | ✅ | ✅ |
smallIcon |
string | "ba_notify_icon" |
通知栏小图标资源名,找不到时回落应用图标 | ✅ | — iOS 固定用 App 图标 |
图片只接受本地绝对路径,不接受网络地址(双端一致)。 想显示网络图,先用
uni.downloadFile下来再把tempFilePath传进来。 iOS 侧还支持file://前缀和百分号编码路径。 Android 的渠道属性(声音 / 震动 / 呼吸灯)只在渠道第一次创建时生效,之后改参数不会动已建渠道——这是系统限制,和原插件一致。
七种样式示例
// 0 普通
notify.show({ notifyType: 0, channelID: '0', channelName: '普通通知', ID: 0,
title: '普通通知', content: 'content', extend: '附加参数' })
// 1 大图(bigUrl 必填本地路径,thumbUrl 是右上角小图)
notify.show({ notifyType: 1, channelID: '1', channelName: '大图通知', ID: 1,
title: '大图通知', content: 'content', bigUrl: '/sdcard/.../big.png', thumbUrl: '/sdcard/.../thumb.png' })
// 2 按钮
notify.show({ notifyType: 2, channelID: '2', channelName: '按钮通知', ID: 2,
title: '按钮通知', content: 'content', leftBtnText: '左按钮', rightBtnText: '右按钮', extend: '附加参数' })
// 3 HeadUp(渠道重要性 HIGH,会横幅弹出)
notify.show({ notifyType: 3, channelID: '3', channelName: 'HeadUp', ID: 3,
title: 'HeadUp', content: 'content', leftBtnText: '左按钮', rightBtnText: '右按钮', thumbUrl: '/sdcard/.../thumb.png' })
// 4 消息盒子
notify.show({ notifyType: 4, channelID: '4', channelName: '消息盒子', ID: 4,
title: 'mailbox', content: 'content', msgList: ['消息1', '消息2', '消息3'], thumbUrl: '/sdcard/.../thumb.png' })
// 5 多行
notify.show({ notifyType: 5, channelID: '5', channelName: '多行通知', ID: 5,
title: '多行通知', content: '《一代人》\n黑夜给了我黑色的眼睛\n我却用它寻找光明' })
// 6 进度(同一个 ID 反复 show 就是刷新进度;跑满显示 finishText)
notify.show({ notifyType: 6, channelID: '6', channelName: '进度通知', ID: 6,
title: '下载文件', content: '正在下载', maxProgress: 100, progress: 40, finishText: '下载完成' })
// 常驻通知(侧滑删不掉,只有 clear/clearById 能清)
notify.show({ notifyType: 0, channelID: '7', channelName: '常驻渠道', ID: 7,
title: '常驻通知', content: '侧滑删不掉', ongoing: true, autoCancel: false, isSound: false })
点击事件参数
点整条通知、点左按钮、点右按钮,回传的都是同一组字段(code 一类的返回字段不在这张表里):
| 字段 | 说明 |
|---|---|
BaNotifyChannelID |
渠道 id |
BaNotifyChannelName |
渠道名 |
BaNotifyID |
通知 id(字符串) |
notifyType |
样式类型(字符串) |
extend |
你传的附加参数;没传就没有这个键 |
Notify-Click |
只有点按钮时才有:leftBtn / rightBtn;点整条没有这个键 |
leftBtnText / rightBtnText |
传了按钮文字才会带 |
Android 接法(与原插件一致)
// 冷启动:参数在 plus.runtime.arguments 里
const args = plus.runtime.arguments
if (args) {
const p = JSON.parse(args)
console.log('点了通知', p.BaNotifyID, p['Notify-Click'])
}
// 应用在后台 / 前台:走 newintent
plus.globalEvent.addEventListener('newintent', () => {
const p = JSON.parse(plus.runtime.arguments || '{}')
console.log('newintent', p)
})
iOS 接法
import { notify } from '@/uni_modules/zeng-notify'
notify.onClick((p) => {
console.log('iOS 点击', p.BaNotifyID, p['Notify-Click'])
notify.clearLastClick()
})
// 冷启动可能早于 onClick 注册,用 getLastClick 兜底
const last = notify.getLastClick()
if (last) {
console.log('补处理冷启动点击', last)
notify.clearLastClick()
}
iOS 的点击参数会缓存在 UserDefaults(com.zeng.notify.lastClick),
插件在 applicationDidFinishLaunching 之前就装好了 UNUserNotificationCenter 代理,所以冷启动点通知不会丢事件。
iOS 与 Android 的差异
iOS 系统本身没有这些能力,插件按「能对齐就对齐、对齐不了就退化」处理:
| 能力 | Android | iOS 实际表现 |
|---|---|---|
| 通知渠道 | 真渠道,可在系统设置里单独关 | 用 threadIdentifier 归组,系统设置里没有渠道开关 |
进度条 notifyType=6 |
原生进度条 | 文字进度条 ▰▰▰▰▱▱▱▱▱▱ 40%,indeterminate 显示「处理中」,跑满显示 finishText |
消息盒子 notifyType=4 |
InboxStyle 逐行展开 |
最多 5 行拼进正文,副标题写「N 条消息」 |
大图 notifyType=1 |
BigPictureStyle 展开即大图 |
作为通知附件,长按 / 下滑展开查看 |
按钮 notifyType=2 |
通知上直接显示按钮 | 注册为通知动作(category),长按 / 下拉展开后可点 |
常驻 ongoing |
FLAG_NO_CLEAR,侧滑删不掉 |
❌ 系统不允许,通知始终可滑删 |
autoCancel=false |
点击后保留 | ❌ 点击必消失 |
ticker / isVibrate / isLights |
支持 | ❌ 系统无对应 API,参数被忽略 |
smallIcon |
支持自定义资源名 | ❌ 固定显示 App 图标 |
| 前台时弹通知 | 支持 | 支持(代理里返回 banner + list + sound) |
另外 iOS 的本地通知是由系统托管的:App 被杀掉之后,已经发出去的通知仍然留在通知中心,但不会再有新的; 需要「杀掉还能继续弹」的场景请配合服务端推送(unipush / APNs),不在本插件范围内。
常见问题
Q:Android 通知不显示?
先查 isNotifyEnabled。Android 13+ 必须授予 POST_NOTIFICATIONS;8.0+ 还要看对应渠道有没有被用户在系统设置里关掉。
Q:ongoing: true 还是能侧滑删掉?
本插件在 Android 8+ 上会同时下 FLAG_ONGOING_EVENT 和 FLAG_NO_CLEAR(实测 flags=0x22)。
如果仍被划掉,检查是不是又用同一个 ID 发了一条 ongoing: false 的通知——同 id 会整条替换。
Q:改了 isSound 没效果?
Android 渠道属性只在渠道首次创建时生效。换个 channelID,或让用户在系统设置里改,或先删掉渠道再建。
Q:大图 / 缩略图不显示?
只接受本地绝对路径。网络图先 uni.downloadFile;相对路径(static/xx.png)需要先转成绝对路径。
Q:iOS 点了按钮没回调?
onClick 只能有一个监听者,重复注册会覆盖;页面 onUnload 里记得别把回调置空后又不重注册。冷启动场景用 getLastClick() 兜底。
目录结构
zeng-notify/
├── package.json
├── readme.md
├── changelog.md
├── utssdk/
│ ├── interface.uts 参数与回调类型
│ ├── app-android/
│ │ ├── index.uts UTS 封装层
│ │ ├── config.json minSdk 21 / abis
│ │ ├── AndroidManifest.xml POST_NOTIFICATIONS + VIBRATE
│ │ └── libs/zeng-notify-core.jar 编译好的 Java 内核
│ └── app-ios/
│ ├── index.uts UTS 封装层 + NotifyHookProxy 启动钩子
│ └── ZengNotifyNative.swift iOS 原生内核
├── native-core/
│ ├── src/com/zeng/notify/NotifyCore.java Java 内核源码
│ └── build.sh javac → jar → 自动拷进 libs
└── examples/
├── notify-demo.vue uni-app 示例页(七种样式全按钮)
└── README.md 示例搭建说明
改了 native-core/src 下的 Java 之后重新打 jar:
cd uni_modules/zeng-notify/native-core && ./build.sh
然后在 HBuilderX 里重新制作自定义基座。

收藏人数:
购买普通授权版(
试用
使用 HBuilderX 导入示例项目
赞赏(0)
下载 2
赞赏 0
下载 12723332
赞赏 1958
赞赏
京公网安备:11010802035340号