清咔
清咔
  • 发布:2020-10-22 19:20
  • 更新:2022-04-13 18:41
  • 阅读:3662

unipush推送实际开发遇到的问题

分类:HBuilderX

uniPush

对接这个推送真的是一波三折,各种坑层出不断。

详细步骤看文档

当前项目进度:
Android 各家厂商推送注册、ios推送证书(通用)已正确申请、配置、填写、上传等等前置操作也完成。

此处记录实际开发问题

注册监听click和receive事件

在App.vue 的生命周期 onLaunch 事件添加事件两个事件监听

   plus.push.addEventListener('receive',function(msg){  

   },false)  

   plus.push.addEventListener('click',function(msg){  

   },false)  
   //tips:推送需要设备唯一id(clientId)  

事件触发逻辑(开发测试所得)

  1. Android
    app前台/后台运行会触发receive事件
    app进程杀掉不会触发receive(走厂商推送)

  2. IOS
    app前/台运行会触发receive事件
    app后台运行(杀掉、锁屏)不会触发rereceive(走厂商推送)
    简单点就是app还活着时候就能接受到receive事件,挂掉(进程结束)就没办法触发这事件了。


安卓真机调试修改以上内容需要重新编译后生效(热更新后没生效)华为手机。


click事件接收到的参数IOS和Android不同

IOS payload返回 对象,Android payload返回字符串;payload层级也有所区别。


如果正常情况下receive事件没有触发可以试试以下步骤

  1. 重新编译运行App(这个很重要)
  2. 登录Dcloud开发者后台测试(创建推送、故障排查)
  3. 如果第二步测试不成功,多半是配置问题。
  4. 如果第二步测试成功,请联系后台检查推送参数格式、推送策略等

    IOS能收到recieve事件,但是收不到通知消息

在开发者后台创建通知消息推送收不到,请检查推送证书(xxx.p12),证书生成看文档。

在开发者后台发的推送可以收到,实际服务器发起的收不到,一般是后台配置问题,我遇到的就是后台没有设置推送策略导致的(默认值惹的祸,最好就是让后台加上)


IOS需要手动清除角标
先上代码:

function claerBadge(){  
      if(plus.os.name.toLowerCase() == 'ios'){  
        //导入ios UIApplication    
        var UIApplication = plus.ios.import("UIApplication");    
        var app = UIApplication.sharedApplication();    
        //获取应用图标的数量    
        // var oldNum = app.applicationIconBadgeNumber();    
        // var newNum = oldNum - 1;    
        //设置应用图标的数量    
        plus.runtime.setBadgeNumber(0);    
        //导入个推原生类    
        var GeTuiSdk = plus.ios.importClass('GeTuiSdk');    
        GeTuiSdk.setBadge(0);  
      }  
    }

IOS通知消息没有声音

后台推送消息需要填写sound:'default'
附:个推文档
文档写的不详细,这里花了不少时间。文档里对这个字段的描述是:

通知铃声文件名,无声设置为“com.gexin.ios.silence”
string类型,非必填、无默认值;

后台的同事按着文档来对接这个字段是没有设置的;
前端对接时候发现能收到消息,但就是没有声音。
首先第一感觉是前端代码是没有问题的,因为可以正常接收;
然后到Dcloud开发者后台测试,发送一条通知消息,正常接收,有声音。
再去检查代码,没有收获。
找后台同事要对接文档(上面链接),仔细查看,发现content-available这个字段,但是后台反馈这个字段是设置了0的,有截图无法反驳,囧。
在去开发者后台查看推送的配置、字段之类的。发现了sound这个字段是有值的(三选一,但都不为空),感觉抓到了点东西,跑去联系后台同事,把sound设成default一试。声音出来了。
PS:也不能说是文档的问题吧,毕竟文档也没有写错,只是没有写的详细而已。


最后附上自己写小段代码,仅供参考;
pushUtils.js

import store from "@/store"  
// 获取设备token ,返回promise  
const getClientId = function() {  
    return new Promise((resolve, reject) => {  
        uni.subscribePush({  
            provider: 'unipush',  
            success: () => {  
                var inf = plus.push.getClientInfo();  
                resolve(inf.clientid)  
            },  
            fail: (e) => {  
                reject(e)  
            }  
        });  
    })  
}  

// 添加receive监听事件,在APP.vue onLaunch 添加  
const InitOnRecivePushMsg = function() {  
    plus.push.addEventListener(  
        "receive",  
        function(msg) {  
            let { content = '{}' } = msg  
            console.log('receive',msg);  
            content = JSON.parse(content)  
            // 添加本地标识,防止本地创建的消息再次触发,导致无限循环  
            if (content.isLocal) return  
            content.isLocal = true  
      // 判断是否要创建本地消息(app在后台时候才触发这个)  
            if (store.getters.isShowPush) {  
                plus.push.createMessage(content.body, JSON.stringify(content), {  
                    title: content.title  
                });  
            }  
        },  
        false  
    );  
}  

// 添加click监听事件,在APP.vue onLaunch 添加  
const InitOnClickPushMsg = function() {  
    plus.push.addEventListener(  
        "click",  
        function(msg) {  
            console.log("点击了click=====================>", msg);  
            let payload = toJson(msg.payload)  
            let params = payload.params || payload // Android 和 IOS 返回的层级不一样,兼容性写法  
            const sessionId = `p2p-${params.from_accid}`;  
            clearMsg()  
      // 判断是否在聊天界面  
            let navigateMethod = store.getters.isChatBoxPage ? 'redirectTo' : 'navigateTo'  
            uni[navigateMethod]({  
                url: `/pages/chats/chatsbox/ChatsBox?to=${params.from_accid}&sessionId=${sessionId}`,  
                success: function() {  
                    uni.hideLoading()  
                },  
                fail: (e) => {  
                    console.log("跳转失败e: ========>", e);  
                }  
            });  
        },  
        false  
    );  
}  

// 工具函数、、、  
const toJson = function(value) {  
    let result  
    try {  
        result = JSON.parse(value)  
    } catch (e) {  
        result = value  
    }  
    return result  
}  

const playTipsSound = function(){  
    //通知音播放  
    let innerAudioContext = uni.createInnerAudioContext();  
    innerAudioContext.autoplay = true;  
    innerAudioContext.src = "/static/inform.mp3"; // 路径要写绝对路径,Android有时会报错 errCode:-5; 莫名其妙  
    innerAudioContext.onPlay(() => {});  
  // IOS播放时会先触发onError事件,乱七八糟,不知道什么原因  
    innerAudioContext.onError((res) => {});    
    innerAudioContext.onEnded(() => { innerAudioContext.destroy() })  
}  

const clearMsg = function(){  
    plus.push.clear()  
}  

function claerBadge(){  
        if(plus.os.name.toLowerCase() == 'ios'){  
            //导入ios UIApplication    
            var UIApplication = plus.ios.import("UIApplication");    
            var app = UIApplication.sharedApplication();    
            //获取应用图标的数量    
            // var oldNum = app.applicationIconBadgeNumber();    
            // var newNum = oldNum - 1;    
            //设置应用图标的数量    
            plus.runtime.setBadgeNumber(0);    
            //导入个推原生类    
            var GeTuiSdk = plus.ios.importClass('GeTuiSdk');    
            GeTuiSdk.setBadge(0);  
        }  
    }  

export default {  
    getClientId,  
    InitOnRecivePushMsg,  
    InitOnClickPushMsg,  
    clearMsg,  
    claerBadge  
}  
4 关注 分享
mikan 梦里追逐 d***@yunfanda.com Simons

要回复文章请先登录注册

nininiccc

nininiccc

感恩分享,请问离线是无法处理消息是吗?比如像支付宝的离线语音播报。
2022-04-13 18:41
4***@qq.com

4***@qq.com

有做离线推送吗。
2020-11-25 10:29
清咔

清咔 (作者)

回复 秋凡 :
感谢指出
2020-11-20 11:34
westgogo

westgogo

我遇到的坑是,不能写在 App.vue中,
只能写在具体的某个页面中,比如第一个页面 pages/index/index.vue中,
但是,但是,事件注册代码,不能独立到别的文件中,也只能直接写在当前页面。

```
import WJF from '@/common/WJF.js';
import CommonTool from '@/common/CommonTool.js';
import PushManager from '@/common/sys/push'
export default {
mixins: CommonTool.getMixin(),
components: {
},
data () {
return {
navigationBarTitleText: 'title',
version: '0.0.1',
};
},
onLoad () {
},
onUnload: function () {
},
mounted () {
this.local_regPushEvent();
},
methods: {
regPushEvent () {
PushManager.regPushEvent();
},
local_regPushEvent () {
const _handlePush = function (message) {
console.log(message);
// IOS payload返回 对象,Android payload返回字符串;payload层级也有所区别。
if (typeof message.payload === 'string') {
message.payload = JSON.parse(payload);
}
/**
* 约定 payload 格式
* type: [naviagte switchTab , web-view] 目前只支持这三种
* path: type 为 [naviagte , switchTab,web-view] 生效
* params: String , 附加参数,如:a=1&b=2 页面跳转,则作为 url 参数传递 ,并使用 encodeURIComponent 编码,固定参数名为 payload
*
*/
message.payload = message.payload || {};
console.log(message);
};
// IOS端在客户端在运行时收到推送消息触发receive事件,离线接收到的推送消息全部进入系统消息中心。点击消息中心的消息触发click
plus.push.addEventListener('click', function (message) {
WJF.ui.alert.successTip('push click');
console.log('app push click');
_handlePush(message);
});
// 只有发送的是透传数据【并且】不是标准格式【并且】当前应用在活动
plus.push.addEventListener('receive', function (message) {
WJF.ui.alert.successTip('push receive');
console.log('app push receive');
_handlePush(message);
});
console.log('============当页2 消息注册完毕=========')
}
}
};
```

调用 local_regPushEvent 这个函数,直接在当前页面注册是可以的。

把代码逻辑独立出来,放到 push.js 并引入,就是不行。
能接收通知,但是点击状态栏的通知,并不能触发 click 事件回调。
而 APP.vue中 无论是直接写,还是采用引入js的方式,都不行。

无语了。
2020-11-11 11:59
秋凡

秋凡

老铁 clear 写错了哦 claerBadge
2020-11-10 17:54
清咔

清咔 (作者)

推送已经对接完毕,以上过程根据记忆所写,仅供参考。
如发现不对之处,欢迎提出。
开发不易,愿没有加班
2020-10-22 19:22