uniapp消息推送 uni-push2(简单记一下)

2,541 阅读5分钟

前排注意 华为的离线推送,要在项目设置--配置SHA256证书指纹,在推送服务--配置--申请自分类权益 要不然离线推送会被限制,刚配置完要等个1天左右

另外这里云函数还缺了个渠道好像,要不然会有问题

uni-push2

官方文档:uniapp.dcloud.net.cn/unipush-v2.…

步骤一:平台配置

这一步没啥好说的,ios很简单,跟着填信息就行了,安卓的生成云端证书再按着证书填信息

image.png

步骤二:推送配置

uniapp.dcloud.net.cn/unipush-v2.…

ios证书比较麻烦,可以参考juejin.cn/post/727478… ios推送证书可以看docs.getui.com/getui/mobil…

步骤三:云空间配置

uniapp.dcloud.net.cn/unipush-v2.…

步骤四:代码

uniapp写法uniapp.dcloud.net.cn/api/plugins…
plus写法www.html5plus.org/doc/zh_cn/p…
为了防止plus运行到浏览器会报错,可以加上条件渲染

/*#ifdef APP-PLUS*/
/*#endif*/

检查是否有推送权限,可行,代码来源www.jb51.net/article/271…

function CheckMsgPowerISOPEN() {
  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);
          }
        },
      });
    }
  }
  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;
    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);
          }
        },
      });
    }
  }
}

云函数
uniPush.sendMessage更多参数文档
下图仅供参考,详细看代码 image.png ios的 安卓也是一样 ①uni-push2 平台的普通消息的,不会主动弹出,需要监听到receive行为自己生成
②uni-push2 平台的透传消息的,会主动弹出,但是无法监听到receive行为
③云函数 force_notification: false为①情况,true为②情况
③云函数 content_available: 0为普通消息,1为静默消息(离线无弹出,在线弹出)

特别特别注意 华为离线推送 content是不能乱填的,其内容要跟自分类权益申请的内容差不多,要不然收不到离线消息

const uniPush = uniCloud.getPushManager({  
	appId: "__UNI__xxxxxx"  
})  
exports.main = async (event) => {  
	let obj = JSON.parse(event.body)  
	const res = await uniPush.sendMessage({  
		"push_clientid": obj.push_clientid, // 设备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, //消息分类,没申请可以不传这个参数  
		"content_available":obj.content_available,//0为普通消息,1为静默消息(离线无弹出,在线弹出)
    })  
};

后端请求云函数推送消息(这里我是写在前端自己触发着测试)

//获取权鉴Token
function ServerPushMsg() {
  function generateRandomNumber(minLength, maxLength) {
    const length =
      Math.floor(Math.random() * (maxLength - minLength + 1)) + minLength;
    let randomNumber = "";
    for (let i = 0; i < length; i++) {
      randomNumber += Math.floor(Math.random() * 10);
    }
    return randomNumber;
  }
  let push_clientid = "xxxxxxxxxxxxx";
  uni.request({
    url: "https://xxxxxxxxxxxxx", //去uniClouds云函数那复制
    method: "POST",
    data: {
      push_clientid: push_clientid, //用户设备cid
      title: generateRandomNumber(10, 32),
      content: "内容内容内容容内内容内容内容内容",
      options: {},
      request_id: generateRandomNumber(10, 32), //消息id(10-32位) 后端定义 不能重复 重复不会发消息
      content_available:0,
    },
    success: (res) => {
      console.log("推送的消息为", res);
    },
  });
}

获取客户端推送标识信息

//plus
plus.push.getClientInfo()
//plus异步
plus.push.getClientInfoAsync(
    function (info) {console.log(info);},
    function (e) {console.log("Failed");}
);
//uni异步
uni.getPushClientId({
    success: (res) => {console.log(res.cid);},
    fail(err) {console.log(err);},
});

监听点击行为

<script setup>
    import { onLaunch } from "@dcloudio/uni-app";
    onLaunch((data) => {
        //plus
        plus.push.addEventListener("click",(msg) => {
          console.log("plus点击到消息", msg);
        },false);
        
        //uniapp
        uni.onPushMessage((msg) => {
          if (res.type == "click") {
              console.log("uni点击到消息", msg);
          }
        });
    })
</script>

监听收到消息行为

<script setup>
    import { onLaunch } from "@dcloudio/uni-app";
    onLaunch((data) => {
        //plus
        plus.push.addEventListener("receive",(msg) => {
          console.log("plus收到消息", msg);
        },false);
        
        //uniapp
        uni.onPushMessage((msg) => {
          if (res.type == "receive") {
              console.log("uni收到消息", msg);
          }
        });
    })
</script>

设置应用角标,角标数后端获取

plus.runtime.setBadgeNumber(0);

我这么写的

//检查是否有推送权限
export function CheckMsgPowerISOPEN() {
  /*#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);
          }
        },
      });
    }
  }
  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;
    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*/
}

//关闭监听服务
export function offPushMessage() {
  uni.offPushMessage()
  console.log("消息推送监听已关闭");
}

//开启监听服务
export function onPushMessage() {
  uni.onPushMessage((res) => {
    console.log("uniapp启动监听推送消息事件", res);
    if (res.type == "click") {
      console.log("这是点击事件", res.data);
    } else if (res.type == "receive") {
      const msgStores = msg()
      msgStores.reqestlist()
      console.log("这是应用从推送服务器接收到推送消息事件", res.data);
      uni.createPushMessage(res.data); 
    }
  });
}

//设置角标数目
export function setBadgeNumber(num) {
  /*#ifdef APP-PLUS*/
  plus.runtime.setBadgeNumber(Number(num));
  /*#endif*/
}

//登录时 检查是否有推送权限 & 开启监听
export function loginSet() {
  CheckMsgPowerISOPEN()
  onPushMessage()
  
  这里请求后端获取有几条未读消息,设置角标数,一般都是在store处理存储
}

//登出时 取消监听消息推送 & 设置角标数为0
export function logoutSet(){
  offPushMessage()
  setBadgeNumber(0)
}

app 加载时(onLaunch) 调用CheckMsgPowerISOPEN(需要判断是否是登陆状态,避免无所谓的调用),登录成功时调用loginSet,登出时调用logoutSet,另外app.vue中onLoad调用 unipushRun(),onHide调用offPushMessage(),如果在onlaunch()调用unipushRun()的话就不需要offPushMessage()