消息推送属于敏感操作,只能直接或间接由服务端触发。传统的三方push服务,需要开发者在服务端配置密钥或证书,根据服务器端文档签名获取token,再向相关URL接口发起网络请求......
而UniPush2.0,开发者无需关心证书、签名、服务器端文档,使用简单。云函数通过 uni-push服务端sdk,即uni-cloud-push
的API即可直接执行uniPush所有操作。
uni-push的服务端sdk的体积不小,没有内置在云函数中。在需要操作uni-push的云函数里,开发者需手动配置uni-cloud-push
扩展库。 (uniCloud扩展库,是uniCloud自带API中不常用且包体积较大的部分,被独立为扩展库,可以由开发者自行选择是否使用该扩展库)。
一、云函数的创建
在项目文件最外层右键创建unicloud云开发环境
右键创建好的目录选择要关联的云服务空间或项目
打开uniCloud 在云函数目录下右键新建一个云函数,添加推送公共模块
二、云函数的执行
在云函数文件目录右键(或按快捷键ctrl + r)-> 上传并运行云函数,此时你的客户端将收到推送消息(应用关闭时为通知栏消息,在线时代码监听到推送消息)。
云函数中调用uni-cloud-push扩展库的sendMessage方法,向客户端推送消息
javascript
// 简单的使用示例
'use strict';
const uniPush = uniCloud.getPushManager({appId:"__UNI__XXXXXX"}) //注意这里需要传入你的应用appId
exports.main = async (event, context) => {
return await uniPush.sendMessage({
"push_clientid": "xxx", //填写上一步在uni-app客户端获取到的客户端推送标识push_clientid
"force_notification":true, //填写true,客户端就会对在线消息自动创建"通知栏消息"。
"title": "推送标题",
"content": "推送内容哈哈哈哈",
"payload": {
"text":"体验一下uni-push2.0"
}
"options":{
"HW": {
// 1 表示华为测试消息,华为每个应用每日可发送该测试消息500条,此target_user_type 参数请勿发布至线上。
"/message/android/target_user_type":1
}
}
})
};
在线消息无额度限制。离线推送各厂商的限额,详见: 厂商通道限额
如果你希望当应用在线时,也通过"通知栏消息"来提醒用户;可以通过以下两种方式实现:
- 监听到消息内容后,根据业务需要自己判断是否要创建"通知栏消息",需要就调用创建本地消息API uni.createPushMessage手动创建通知栏消息。
- 服务端执行推送时,传递参数force_notification:true,客户端就会自动创建"通知栏消息"(此时你监听不到消息内容),当用户点击通知栏消息后,APP才能监听到消息内容。
检查确认当前 app 的通知栏权限开启后,则可以开始进行推送测试。
运行结果
云函数代码示例
javascript
// 简单的使用示例
'use strict';
const uniPush = uniCloud.getPushManager({
appId: ""
}) //注意这里需要传入你的应用appId
exports.main = async (event) => {
console.log("入参", event.body);
let obj = event.body ? JSON.parse(event.body) : {};
try {
const res = await uniPush.sendMessage({
"push_clientid": obj.cids.split(","), // 设备id,支持多个以数组的形式指定多个设备,如["cid-1","cid-2"],数组长度不大于1000
"title": obj.title, // 标题
"content": obj.content, // 内容
"payload": obj.data, // 数据
"force_notification": true, // 服务端推送 需要加这一句
"request_id": obj.request_id, //请求唯一标识号,10-32位之间;如果request_id重复,会导致消息丢失
// "options":obj.options, //消息分类,没申请可以不传这个参数
})
return {
msg:"消息发送成功"
}
} catch (e) {
//TODO handle the exception
return {
errCode: 1,
errMsg: e.toString()
}
}
};
三、云函数URL化
在 uniCloud 的云函数中,加载扩展库 uni-cloud-push,直接调用相关 API,无需额外的服务端配置。
传统服务器开发者(例如:Java、php、python等)需要把这个 云函数URL化 后变成 http 接口,再由代码调用这个 http 接口。
在unicloud控制台中点击查看已经上传的云函数配置url
api 工具测试请求
结果
四、客户端监听消息
客户端监听推送消息的代码,需要在收到推送消息之前被执行。所以应当写在应用一启动就会触发的 应用生命周期 onLaunch中。
示例代码:
ini
onLaunch: function() {
uni.onPushMessage((res) => {
console.log("收到推送消息:", res); //监听推送消息
if (res.data.payload) {
let id = res.data.payload.ids;
let role = uni.getStorageSync("role");
if (id) {
if (role == 1) {
if (res.data.payload.orderStatus == 1) {
uni.switchTab({
url: '/pages/home/driver',
})
} else {
uni.navigateTo({
url: `/pages/driverOrder/detail?id=${id}&type=push`,
});
}
return;
}
uni.navigateTo({
url: `/pages/home/order?id=${id}&type=push`,
});
}
}
});
},
由于使用了uniPush(发送消息通知)功能,在应用首次启动时ios会弹出"发送通知"系统授权框,安卓并不弹,所以我们需要自己写一个检测消息通知是否打开,这也方便了我们以后随时提醒用户打开消息通知
ini
// 判断消息通知是否打开
//监听 是否开启权限
export const getNotificationEnabled = () => {
// #ifdef APP-PLUS
if (plus.os.name == 'Android') { // 判断是Android
var main = plus.android.runtimeMainActivity();
var pkName = main.getPackageName();
var uid = main.getApplicationInfo().plusGetAttribute("uid");
var NotificationManagerCompat = plus.android.importClass("android.support.v4.app.NotificationManagerCompat");
//android.support.v4升级为androidx
if (NotificationManagerCompat == null) {
NotificationManagerCompat = plus.android.importClass("androidx.core.app.NotificationManagerCompat");
}
var areNotificationsEnabled = NotificationManagerCompat.from(main).areNotificationsEnabled();
// 未开通'允许通知'权限,则弹窗提醒开通,并点击确认后,跳转到系统设置页面进行设置
if (!areNotificationsEnabled) {
uni.showModal({
title: '通知权限开启提醒',
content: '您还没有开启通知权限,无法接受到消息通知,请前往设置!',
showCancel: false,
confirmText: '去设置',
success: function(res) {
if (res.confirm) {
var Intent = plus.android.importClass('android.content.Intent');
var Build = plus.android.importClass("android.os.Build");
//android 8.0引导
if (Build.VERSION.SDK_INT >= 26) {
var intent = new Intent('android.settings.APP_NOTIFICATION_SETTINGS');
intent.putExtra('android.provider.extra.APP_PACKAGE', pkName);
} else if (Build.VERSION.SDK_INT >= 21) { //android 5.0-7.0
var intent = new Intent('android.settings.APP_NOTIFICATION_SETTINGS');
intent.putExtra("app_package", pkName);
intent.putExtra("app_uid", uid);
} else { //(<21)其他--跳转到该应用管理的详情页
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
var uri = Uri.fromParts("package", mainActivity.getPackageName(), null);
intent.setData(uri);
}
// 跳转到该应用的系统通知设置页
main.startActivity(intent);
}
}
});
}
} else if (plus.os.name == 'iOS') { // 判断是ISO
var isOn = undefined;
var types = 0;
var app = plus.ios.invoke('UIApplication', 'sharedApplication');
var settings = plus.ios.invoke(app, 'currentUserNotificationSettings');
if (settings) {
types = settings.plusGetAttribute('types');
plus.ios.deleteObject(settings);
} else {
types = plus.ios.invoke(app, 'enabledRemoteNotificationTypes');
}
plus.ios.deleteObject(app);
isOn = (0 != types);
console.log("消息通知是否打开", isOn)
if (isOn === false) {
uni.showModal({
title: '通知权限开启提醒',
content: '您还没有开启通知权限,无法接受到消息通知,请前往设置!',
showCancel: false,
confirmText: '去设置',
success: function(res) {
if (res.confirm) {
var app = plus.ios.invoke('UIApplication', 'sharedApplication');
var setting = plus.ios.invoke('NSURL', 'URLWithString:', 'app-settings:');
plus.ios.invoke(app, 'openURL:', setting);
plus.ios.deleteObject(setting);
plus.ios.deleteObject(app);
}
}
});
}
}
// #endif
};