uni-app实现消息推送需分清本地通知与系统推送:调用uni.showLocalNotification前必须检查权限、Android渠道声明及iOS声音配置,缺一即静默失败。
uni-app 实现消息推送通知,核心不是选哪个 sdk,而是分清「本地通知」和「系统推送」——前者是 app 自己定时弹的(比如打卡提醒),后者是服务端发、关机后也能收(比如订单状态变更)。混用会导致 ios 不响、android 不显示、控制台还完全不报错。
uni.showLocalNotification 调用前必须检查的三件事
这个 API 看似一行代码就能用,但漏掉任意一项,通知就静默失败:
- 权限没开:
uni.getSetting检查res.authSetting['scope.notification']是否为true;不是就立刻调uni.openSetting引导用户开启 - Android 渠道缺失:targetSdkVersion ≥ 26 后,
channelId不仅要传,还必须提前在原生层声明(manifest.json的permissions和android配置里补全);不声明 = 系统直接丢弃 - iOS 静音陷阱:
sound: 'default'必须显式传,且 Xcode 中的Background Modes必须勾选Remote notifications;否则即使前台运行也不播放提示音
示例写法(含兜底):
uni.getSetting({ success: (res) => {
if(res.authSetting['scope.notification'] !== true) {
uni.openSetting({ success: openRes => {
if(openRes.authSetting['scope.notification']) showNoti();
}});
return;
}
showNoti();
}});
function showNoti() {
uni.showLocalNotification({
title: '打卡提醒',
body: '请在10分钟内完成签到',
date: Date.now() + 5 * 60 * 1000,
channelId: 'work',
sound: 'default'
});
}plus.notification.create 是更底层但更可控的替代方案
当 uni.showLocalNotification 因渠道或后台限制失效时,它能绕过部分限制,但代价是手动处理更多细节:
- iOS 上它只在 App 前台有效,进入后台后调用直接返回
err: "Not supported" - Android 必须先调
plus.notification.setChannel创建渠道,否则create会静默失败 - 点击通知后不会自动跳转页面,得手动监听
plus.notification.addEventListener('click', )并调uni.navigateTo
真机调试必须用「自定义基座」,默认基座无效
plus.push.getClientInfo() 返回 null 或空字符串?不是代码问题,是基座没对:
- 默认基座(HBuilderX 自带的调试 App)不包含任何厂商 SDK,
uni.getPushClientId()拿不到有效值 - 必须在 HBuilderX 中点击「运行」→「运行到手机或模拟器」→「制作自定义调试基座」,过程中确保登录账号与 DCloud 开发者中心一致
- 制作完成后,运行时务必选择该基座,而不是“使用标准基座”
- 云打包产出的 APK/IPA 也必须基于同一账号、同一 AppID 构建,否则 cid 无法被 uniPush 后台识别
manifest.json 的 push 配置必须和厂商后台完全一致
填错一个字符,Android 离线推送就失效,通知栏压根不弹。这不是逻辑问题,是身份认证失败:
- 华为:
huawei下的appid必须和 AGC 控制台「项目设置 → 应用信息」里显示的一模一样,包括大小写和前后空格;漏掉HUAWEI-前缀或写成com.xxx.hms都会返回空 cid - 小米:
appkey不是控制台首页看到的“AppKey”,得进「推送服务 → 应用配置」页面单独找;appid和appkey必须成对,且仅适用于小米推送通道 - OPPO/VIVO:
appKey/appSecret要填在对应对象下,不能塞进meizu或漏掉;它们还要求手动开启系统级权限:通知栏开关 + 自启动白名单 - 别忘了加
"permissions": ["android.permission.POST_NOTIFICATIONS"]—— Android 12+ 强制要求,没这句,连权限弹窗都不出现
最容易被忽略的是:服务端只能走 uniCloud.getPushManager,且 appId 必须来自 DCloud 开发者中心;你不能在自己的 Node.js 服务里调这个 API,也不能把云函数部署到非 DCloud 的云环境。


















