
简体中文
uni-push是DCloud与合作伙伴个推共同推出的统一推送服务。用于从服务器端推送消息到客户端。
它包括在线推送、离线推送,聚合了Apple、华为、小米、OPPO、VIVO、魅族、荣耀(3.99+)、Google等多个手机厂商的推送通道。
若不使用服务器推送,仅想创建手机通知栏本地消息,也需要使用本模块的API。
它是一个云端一体的业务,涉及多份文档:
获取客户端唯一的推送标识
Web | 微信小程序 | Android | iOS | HarmonyOS |
---|---|---|---|---|
4.27 | 4.41 | 3.98 | 4.18 | 4.61 |
名称 | 类型 | 必填 | 默认值 | 兼容性 | 描述 | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
options | GetPushClientIdOptions | 是 | - | - | |||||||||||||||||||||||||
|
名称 | 类型 | 必备 | 默认值 | 兼容性 | 描述 |
---|---|---|---|---|---|
cid | string | 是 | - | 个推客户端推送id,对应uni-id-device表的push_clientid | |
errMsg | string | 是 | - | 错误描述 |
启动监听推送消息事件
Web | 微信小程序 | Android | iOS | HarmonyOS |
---|---|---|---|---|
4.27 | 4.41 | 3.98 | 4.18 | 4.61 |
名称 | 类型 | 必填 | 默认值 | 兼容性 | 描述 |
---|---|---|---|---|---|
callback | (result: OnPushMessageCallbackResult) => void | 是 | - | - |
名称 | 类型 | 必备 | 默认值 | 兼容性 | 描述 | |||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
type | string | 是 | - | 事件类型 - click 从系统推送服务点击消息启动应用事件 - receive 应用从推送服务器接收到推送消息事件 | ||||||||||
| ||||||||||||||
data | UTSJSONObject | 是 | - | 消息内容 |
onPushMessage
,那么事件也会多次触发,所以当不需要监听的时候需要offPushMessage
。关闭推送消息监听事件,iOS端调用会关闭所有监听。
Web | 微信小程序 | Android | iOS | HarmonyOS |
---|---|---|---|---|
4.27 | 4.41 | 3.98 | 4.18 | 4.61 |
名称 | 类型 | 必填 | 默认值 | 兼容性 | 描述 |
---|---|---|---|---|---|
callback | (result: OnPushMessageCallbackResult) => void | 是 | - | - |
名称 | 类型 | 必备 | 默认值 | 兼容性 | 描述 | |||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
type | string | 是 | - | 事件类型 - click 从系统推送服务点击消息启动应用事件 - receive 应用从推送服务器接收到推送消息事件 | ||||||||||
| ||||||||||||||
data | UTSJSONObject | 是 | - | 消息内容 |
由于各大厂商限制推送频次,当使用厂商离线推送的时,需要在不同品牌手机后台开通自分类权益,限制数量说明
开通自分类权益后,需要客户端创建channel,因此客户端提供了setPushChannel
来进行channel的创建,通过此Api来创建渠道进行推送。
客户端创建渠道成功后,即可通过云函数进行推送,uni-push2服务端文档。
由于Android通知渠道的机制问题,一旦通知渠道建立,便不能修改此渠道的配置,即使删除渠道后再次创建同channelId名称的渠道,也不会改变原先渠道的配置(除非删除应用),最明显的现象就是铃声动态修改失败,比如调用setPushChannel
时,第一次的设置参数是{"channelId":"test","soundName":"pushsound"}
, 这时你想切换铃音,你的channelId就不能再叫test了,而应该为{"channelId":"test2","soundName":"ring"}
,此时会新建一个渠道。
创建本地通知栏消息
Web | 微信小程序 | Android | iOS | HarmonyOS |
---|---|---|---|---|
x | - | 3.98 | 4.18 | 4.61 |
名称 | 类型 | 必填 | 默认值 | 兼容性 | 描述 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
options | CreatePushMessageOptions | 是 | - | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
名称 | 类型 | 必备 | 默认值 | 兼容性 | 描述 |
---|---|---|---|---|---|
errMsg | string | 是 | - | 错误信息 |
获取通知渠道管理器,Android 8系统以上才可以设置通知渠道,Android 8系统以下返回null,通知渠道介绍,iOS不支持。
Web | 微信小程序 | Android | iOS | HarmonyOS |
---|---|---|---|---|
x | - | 4.25 | x | - |
类型 |
---|
ChannelManager |
setPushChannel 设置推送渠道
Web | 微信小程序 | Android | iOS | HarmonyOS |
---|---|---|---|---|
x | - | 3.98 | x | - |
名称 | 类型 | 必填 | 默认值 | 兼容性 | 描述 | ||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
options | SetPushChannelOptions | 是 | - | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
getAllChannels 获取当前应用注册的所有的通知渠道。
Web | 微信小程序 | Android | iOS | HarmonyOS |
---|---|---|---|---|
x | - | 3.98 | x | - |
类型 |
---|
Array<string> |
设置应用图标上显示的角标数字,注意:不同手机厂商的角标显示规则不同,有部分设备的rom版本不支持显示角标,另有部分rom需要在应用的通知管理里开启桌面角标
配置,才可以设置角标成功。
Web | 微信小程序 | Android | iOS | HarmonyOS |
---|---|---|---|---|
x | - | 4.25 | 4.25 | 4.61 |
名称 | 类型 | 必填 | 默认值 | 兼容性 | 描述 | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
num | number | 是 | - | 要显示的角标数字值,参数为0则表示清除角标数字。 | |||||||||||||||||||
options | BadgeOptions | 否 | - | 小米手机显示角标需要在系统消息中心显示一条通知,此参数用于设置通知的标题(title)和内容(content)。 | |||||||||||||||||||
|
获取通知渠道管理器,Android 8系统以上才可以设置通知渠道,Android 8系统以下返回null,通知渠道介绍 ,iOS不支持。
已废弃,仅为了向下兼容保留,建议使用getPushChannelManager
。
Web | 微信小程序 | Android | iOS | HarmonyOS |
---|---|---|---|---|
x | - | 3.98 | x | - |
类型 |
---|
ChannelManager |
setPushChannel 设置推送渠道
Web | 微信小程序 | Android | iOS | HarmonyOS |
---|---|---|---|---|
x | - | 3.98 | x | - |
名称 | 类型 | 必填 | 默认值 | 兼容性 | 描述 | ||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
options | SetPushChannelOptions | 是 | - | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
getAllChannels 获取当前应用注册的所有的通知渠道。
Web | 微信小程序 | Android | iOS | HarmonyOS |
---|---|---|---|---|
x | - | 3.98 | x | - |
类型 |
---|
Array<string> |
setAppBadgeNumber
。onHide
中设置角标。示例为hello uni-app x alpha分支,与最新HBuilderX Alpha版同步。与最新正式版同步的master分支示例另见
示例
<template>
<!-- #ifdef APP -->
<scroll-view style="flex: 1">
<!-- #endif -->
<view>
<!-- #ifdef APP-ANDROID -->
<button class="normal-button" type="default" @click="handleCreateChannel(true)">
创建通知渠道 | setPushChannel
</button>
<button class="normal-button" type="default" @click="handleGetAllChannels">
获取所有通知渠道信息 | getAllChannels
</button>
<textarea style="width: 100%;" :disabled="true" :value="channelInfo"></textarea>
<!-- #endif -->
<!-- #ifdef APP -->
<button class="normal-button" type="default" @click="handleCreateLocalNotification">
创建本地通知消息 | createPushMessage
</button>
<text class="instructions">
不同手机厂商的角标显示规则不同,有部分设备的rom版本不支持显示角标,另有部分rom需要在应用的通知管理里开启`桌面角标`配置,才可以设置角标成功。\n
部分rom需要在设置中同时开启`通知开关`和`桌面角标`配置,才允许设置角标,例如鸿蒙4.2。 \n
另外针对高版本小米设备,会借助创建通知栏消息来设置角标数,所以设置时需要注意是否有权限创建通知栏消息。
</text>
<button class="normal-button" type="default" @click="handleSetBadge">
设置角标为5 | setAppBadgeNumber(5)
</button>
<button class="normal-button" type="default" @click="handleCleanBadge">
清空角标 | setAppBadgeNumber(0)
</button>
<!-- #endif -->
<button class="normal-button" type="default" @click="handleSendPushMessage">
发送通知消息 | sendPushMessage
</button>
<button class="normal-button uni-common-mb" type="default" @click="handleGetClientId">
获取cid | getPushClientId
</button>
<button class="normal-button" type="default" @click="handleOnPushMessage">
注册回调 | onPushMessage
</button>
<button class="normal-button" type="default" @click="handleOffPushMessage">
注销回调 | offPushMessage
</button>
</view>
<!-- #ifdef APP -->
</scroll-view>
<!-- #endif -->
</template>
<script setup>
// 自动化测试
type TypeJestResult = {
clientId : string,
sendPushMessageRes : number,
onPushMessageType:string,
onPushMessageCallbackInfo:string
}
type TypeIsRegister = {
state:boolean
}
const jestResult = reactive({
clientId:"",
sendPushMessageRes:-1,
onPushMessageType:"",
onPushMessageCallbackInfo:""
} as TypeJestResult)
// 自动化测试
const autoTest = ref(false);
const updateAutoTest = (value : boolean) => {
autoTest.value = value
}
const channelInfo = ref("")
const onPushMessageCallback = (res : OnPushMessageCallbackResult) => {
// 自动化测试
jestResult.onPushMessageType = res.type
jestResult.onPushMessageCallbackInfo = JSON.stringify(res.data)
if (!autoTest.value) {
uni.showModal({
title: "onPushMessage回调信息",
content: `type:${res.type} \n data:${JSON.stringify(res.data)}`
})
}
}
// 为兼容Android测试例中能获取到,此处用reactive定义
const isRegister = reactive({
state:false
} as TypeIsRegister);
const handleOnPushMessage = () => {
if (isRegister.state) {
uni.showToast({
icon: "error",
title: "无需重复注册"
})
return
}
uni.onPushMessage(onPushMessageCallback)
isRegister.state = true
uni.showToast({
title: "成功注册"
})
}
const handleOffPushMessage = () => {
if (!isRegister.state) {
uni.showToast({
icon: "error",
title: "未注册, 无需注销"
})
return
}
uni.offPushMessage(onPushMessageCallback)
isRegister.state = false
uni.showToast({
title: "成功注销"
})
}
const handleCreateChannel = (showToast : boolean) => {
// #ifdef APP-ANDROID
const manager = uni.getPushChannelManager()
manager.setPushChannel({
channelId: "msg-pass",
channelDesc: "留言审核通过",
soundName: "#填写配置的声音文件名#",
enableLights: true,
enableVibration: true,
importance: 4,
lockscreenVisibility: 1
} as SetPushChannelOptions)
if (showToast) {
uni.showToast({
title: "设置渠道成功"
})
}
// #endif
}
const handleGetAllChannels = () => {
// #ifdef APP-ANDROID
const manager = uni.getPushChannelManager()
console.log("channels : " + manager.getAllChannels());
channelInfo.value = `渠道信息为: \n ${manager.getAllChannels()}`
// #endif
}
const handleCreateLocalNotification = () => {
if (uni.getAppAuthorizeSetting().notificationAuthorized == "authorized") {
handleCreateChannel(false)
const date = new Date();
const hour = date.getHours()
const minute = date.getMinutes()
const second = date.getSeconds()
const formateTime = (target : number) : string => {
return target < 10 ? `0${target}` : `${target}`
}
uni.createPushMessage({
title: "主标题(title)",
content: `内容(content),创建时间: ${formateTime(hour)}:${formateTime(minute)}:${formateTime(second)}`,
cover: false,
channelId: "msg-pass",
when: Date.now() + 10000,
icon: "/static/uni.png",
sound: "system",
delay: 1,
payload: {
pkey: "pvalue1"
},
// #ifdef APP-HARMONY
category: "SOCIAL_COMMUNICATION",
// #endif
// #ifndef APP-HARMONY
category: "IM",
// #endif
success(res) {
console.log("res: " + res);
uni.hideToast()
uni.showToast({
title: "创建本地通知消息成功"
})
},
fail(e) {
console.log("fail :" + e);
uni.hideToast()
uni.showToast({
title: "创建本地通知消息失败",
icon: "error"
})
}
})
} else {
uni.showToast({
title: "请在设置中开启通知权限",
icon: "error"
})
}
}
async function getPushClientId(): Promise<string>{
let pushClientId = '';
let res:void = await new Promise<void>(resolve => {
uni.getPushClientId({
success: (res: GetPushClientIdSuccess) => {
console.log(res.cid)
pushClientId = res.cid
resolve()
},
fail: (err: GetPushClientIdFail) => {
resolve()
console.error(err);
if (err.message.includes('uniPush is not enabled')) {
uni.showModal({
title: '获取cid失败',
content: '当前项目未启用uni-push,检查manifest.json中的uni-push配置',
showCancel: false
});
} else if (err.message.includes('getPushClientId:fail register fail: {\"errorCode\":1,\"errorMsg\":\"\"}')) {
uni.showModal({
title: '获取cid失败',
content: '当前项目未开通uni-push,开通文档:https://uniapp.dcloud.net.cn/unipush-v2.html#%E7%AC%AC%E4%B8%80%E6%AD%A5-%E5%BC%80%E9%80%9A',
showCancel: false
});
} else {
uni.showToast({
title: `获取cid失败`,
icon: "error"
})
}
}
})
})
return pushClientId
}
const handleGetClientId = async():Promise<void> =>{
uni.showLoading({
title: "正在获取cid",
})
const cid = await getPushClientId()
if (cid != '') {
// 自动化测试
jestResult.clientId = cid
if (!autoTest.value) {
uni.showModal({
title: "获取cid",
content: "获取cid成功" + cid,
showCancel: false
})
}
}
uni.hideLoading()
}
const handleSendPushMessage = async():Promise<void>=> {
const pushClientId = await getPushClientId()
if (pushClientId == ''){
return
}
const uniPushCo = uniCloud.importObject("uni-push-co")
try {
const res = await uniPushCo.sendPushMessage(pushClientId)
// 自动化测试
jestResult.sendPushMessageRes = res.errCode as number
if (!autoTest.value) {
uni.showToast({
title: "发送通知消息成功"
})
}
} catch (err:any) {
const error = err as UniCloudError
console.error(error)
if (!autoTest.value) {
uni.showToast({
title: "发送通知消息失败",
icon: "error"
})
}
}
}
const handleSetBadge = () => {
if (uni.getDeviceInfo().deviceBrand?.toLowerCase() == "xiaomi") {
if (uni.getAppAuthorizeSetting().notificationAuthorized == "authorized") {
uni.setAppBadgeNumber(5, {
title: "AppName",
content: "您有5条未读消息"
} as BadgeOptions)
uni.showToast({
title: "设置应用角标数为5"
})
} else {
uni.showToast({
title: "请在设置中开启通知权限",
icon: "error"
})
}
} else {
uni.setAppBadgeNumber(5)
uni.showToast({
title: "设置应用角标数为5"
})
}
}
const handleCleanBadge = () => {
if (uni.getDeviceInfo().deviceBrand?.toLowerCase() == "xiaomi") {
if (uni.getAppAuthorizeSetting().notificationAuthorized == "authorized") {
uni.setAppBadgeNumber(0, {} as BadgeOptions)
uni.showToast({
title: "清空应用角标数"
})
} else {
uni.showToast({
title: "请在设置中开启通知权限",
icon: "error"
})
}
} else {
uni.setAppBadgeNumber(0)
uni.showToast({
title: "清空应用角标数"
})
}
}
// 自动化测试
defineExpose({
jestResult,
autoTest,
updateAutoTest,
isRegister,
handleSendPushMessage,
handleGetClientId,
handleOnPushMessage,
handleOffPushMessage
})
</script>
<style>
.normal-button {
width: 100%;
}
.instructions {
margin-top: 10px;
margin-left: 10px;
margin-right: 10px;
background-color: #eee;
}
</style>
名称 | 类型 | 必备 | 默认值 | 兼容性 | 描述 |
---|---|---|---|---|---|
errMsg | string | 是 | - | 错误信息 |
在nativeResources/android目录可以配置图片和声音的二进制文件资源。
关于图标的配置,需要创建nativeResources目录, 放置对应分辨率的图片资源即可(打包后生效),目录配置如下
├── nativeResources
│ └── android
│ └── res
│ ├── drawable-ldpi
│ │ ├── push.png // 分辨率要求48x48
│ │ └── push_small.png // 分辨率要求18x18
│ ├── drawable-mdpi
│ │ ├── push.png // 分辨率要求64x64
│ │ └── push_small.png // 分辨率要求24x24
│ ├── drawable-hdpi
│ │ ├── push.png // 分辨率要求96x96
│ │ └── push_small.png // 分辨率要求36x36
│ ├── drawable-xhdpi
│ │ ├── push.png // 分辨率要求128x128
│ │ └── push_small.png // 分辨率要求48x48
│ ├── drawable-xxhdpi
│ │ ├── push.png // 分辨率要求192x192
│ │ └── push_small.png // 分辨率要求72x72
│ ├── drawable-xxxhdpi
│ │ └── push_small.png // 分辨率要求96x96
│ └── raw
│ └── pushsound.mp3 // 声音文件, 自定义推送铃音时使用
有些场景,如到账提醒,需要自定义通知声音。
setPushChannel
设置新建渠道时,soundName
字段的值为目录nativeResources->android->res->raw中存放的音频文件名称,(打包后生效)
注意不要带文件的后缀,比如pushsound.mp3
文件,例:
const channelManager = getChannelManager()
channelManager.setPushChannel({
channelId: "test1",
channelDesc: "test1 desc",
soundName: "pushsound"
})
很多Android应用升级下载apk时会在通知栏显示下载进度。
该功能已经内置到uni升级中心中,此开源模板可直接使用。
需要使用uts插件,见插件市场
getPushClientId
或者onPushMessage
时,才会初始化个推SDK,所以开发者要确保弹出隐私框之前不调用此两项API。