uniapp消息推送云函数

消息推送属于敏感操作,只能直接或间接由服务端触发。传统的三方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  
              }  
        }  
    })  
};

在线消息无额度限制。离线推送各厂商的限额,详见: 厂商通道限额

如果你希望当应用在线时,也通过"通知栏消息"来提醒用户;可以通过以下两种方式实现:

  1. 监听到消息内容后,根据业务需要自己判断是否要创建"通知栏消息",需要就调用创建本地消息API uni.createPushMessage手动创建通知栏消息。
  1. 服务端执行推送时,传递参数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  
};
相关推荐
ZJ_.11 分钟前
WPSJS:让 WPS 办公与 JavaScript 完美联动
开发语言·前端·javascript·vscode·ecmascript·wps
GIS开发特训营16 分钟前
Vue零基础教程|从前端框架到GIS开发系列课程(七)响应式系统介绍
前端·vue.js·前端框架·gis开发·webgis·三维gis
Cachel wood42 分钟前
python round四舍五入和decimal库精确四舍五入
java·linux·前端·数据库·vue.js·python·前端框架
学代码的小前端43 分钟前
0基础学前端-----CSS DAY9
前端·css
joan_851 小时前
layui表格templet图片渲染--模板字符串和字符串拼接
前端·javascript·layui
m0_748236111 小时前
Calcite Web 项目常见问题解决方案
开发语言·前端·rust
Watermelo6172 小时前
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
开发语言·前端·javascript·算法·数据挖掘·数据分析·ecmascript
m0_748248942 小时前
HTML5系列(11)-- Web 无障碍开发指南
前端·html·html5
m0_748235612 小时前
从零开始学前端之HTML(三)
前端·html
一个处女座的程序猿O(∩_∩)O4 小时前
小型 Vue 项目,该不该用 Pinia 、Vuex呢?
前端·javascript·vue.js