x***@sina.com
x***@sina.com
  • 发布:2019-11-30 21:13
  • 更新:2023-09-13 09:38
  • 阅读:21665

5+App使用UniPush发送消息,App在线、离线均能收到消息推送,并在通知栏进行提醒,苹果、华为、小米手机均测试通过

分类:HTML5+

【1】本文档中使用的全是逶传消息,没有使用个推的其他消息
【2】需要开通UniPush功能,并在华为、小米开发者中添加App,并开通Push权限,目前不需要上架各厂商应用市场就可以使用,后续不知道需要不需要
【3】本实例使用Java后台开发,其他语言请自行翻译
【5】关于receive事件,只有发送的是透传数据【而且】不是标准格式【而且】当前应用在活动,这3个条件同时满足,才可以响应receive事件!!!,但是消息中心并没有消息展示!!!需要创建本地消息!!!才能在消息中心提醒,对于IOS的,一定要控制死循环!!!【重要】【重要】【重要】
只有APP在线时,才会触发receive事件,透传消息不会触发系统消息,需要创建本地消息【重要】【重要】【重要】
【6】关于click事件,click一定是点击通知栏的消息,才能触发!!! 下面两句话很重要
【APP在线】,收到透传消息通过,不会提醒至通知栏目,需要发送本地消息,再进行点击触发的点击事件。
【APP离线】,收到离线透传消息,必须通过Java后台的Intent字符串携带payload,且符合格式才能触发click事件,格式不符合不会触发。
【7】厂商推送需要设置的Intent字符串格式,请将${packageName},${title},${content},${payload}替换为正确的内容
${packageName} 代表应用包名
${title} 通知的标题
${content} 通知的内容
${payload} 其他附加参数,请用 JSON.toJSONString(payload)进行转码。

intent:#Intent;launchFlags=0x04000000;action=android.intent.action.oppopush;package=${packageName};component=${packageName}/io.dcloud.PandoraEntry;S.UP-OL-SU=true;S.title=${title};S.content=${content};S.payload=${payload};end

【8】APP端的javaScript代码,不需要必须写在第一个页面,我的项目写在了里面的页面,只要App启动后能打开这个页面就可以:

        //收到透传消息  
        //只有APP在线时,才会触发receive事件,透传消息不会触发系统消息,需要创建本地消息  
        plus.push.addEventListener("receive", function(msg) {  
            console.log("(receive):" + JSON.stringify(msg));  
            if (app.isIOS()) { //如果是IOS  
                var payload = msg.payload;  
                //【APP离线】收到消息,但没有提醒(发生在一次收到多个离线消息时,只有一个有提醒,但其他的没有提醒)  
                //【APP在线】收到消息,不会触发系统消息,需要创建本地消息,但不能重复创建。必须加msg.type验证去除死循环                
                if (msg.aps == null && msg.type == "receive") {   
                    var messageTitle = payload.messageTitle;  
                    var messageContent = payload.messageContent;  
                    //创建本地消息,发送的本地消息也会被receive方法接收到,但没有type属性,且aps是null  
                    plus.push.createMessage(messageContent, JSON.stringify(payload), {title: messageTitle});  
                }  
            }  
            if (app.isAndroid()) { //如果是Android,当APP在线时,收到透传消息不会进入系统消息,需要发送本地提醒。  
                var payload = JSON.parse(msg.payload);  
                var messageTitle = payload.messageTitle;  
                var messageContent = payload.messageContent;  
                plus.push.createMessage(messageContent, msg.payload, {title: messageTitle});  
            }  
        }, false);  

        //消息点击事件  
        //【APP在线】,收到透传消息通过,不会提醒至通知栏目,需要发送本地消息,再进行点击触发的点击事件。  
        //【APP离线】,收到离线透传消息,必须通过Java后台的Intent字符串携带payload,且符合格式才能触发click事件,格式不符合不会触发。  
        plus.push.addEventListener("click", function(msg) {  
            console.log("(click):" + JSON.stringify(msg));  
            if (app.isIOS()) { //如果是IOS  
                var payload;  
                if (msg.type == "click") { //APP离线点击包含click属性,这时payload是JSON对象  
                    payload = msg.payload;  
                } else { //APP在线,收到消息不会包含type属性,这时的payload是JSON字符串,需要转为JSON对象  
                    payload = JSON.parse(msg.payload);  
                }  
                if (payload != null || payload != undefined) {  
                    var messageType = payload.messageType;  
                    messageClick(messageType, payload);  
                }  
            }  
            if (app.isAndroid()) { //如果是Android,收到playload均是是JSON字符串,需要转为JSON对象  
                var payload = JSON.parse(msg.payload);  
                if (payload != null || payload != undefined) {  
                    var messageType = payload.messageType;  
                    messageClick(messageType, payload);  
                }  
            }  
        }, false);

【9】java后台发送代码 ,代码中注释的内容,本人没有研究明白,未进行测试


    /**  
     * 推送消息至App所有用户,100次/天,每分钟不能超过5次,相同的消息内容,10分钟内不可以重复发送<br/>  
     * 华为,平果测试通过  
     *   
     * @param getuiMessage  
     * @return  
     */  
    public static IPushResult toApp(GetuiMessage getuiMessage) {  
        TransmissionTemplate template = PushTemplate.getTransmissionTemplateWith3rdNotifyInfoAndAPNPayload(getuiMessage.getMessageTitle(),  
                getuiMessage.getMessageContent(), "+1", getuiMessage);  
        AppMessage message = new AppMessage();  
        message.setData(template);  
        message.setOffline(true);  
        message.setOfflineExpireTime(24 * 1000 * 3600);  
        message.setAppIdList(Arrays.asList(GetuiConfig.me.getAppId()));  
        IPushResult ret = GetuiConfig.me.getPush().pushMessageToApp(message);  
        GetuiConfig.logger.info(GetuiConfig.logger.getName() + JSON.toJSONString(ret));  
        return ret;  
    }  

    /**  
     * 推送消息至特定的ClientID,频次限制:没有限制!  
     *   
     * @param getuiMessage 消息对象  
     * @param clientId     接收的ClientId  
     * @return  
     */  
    public static IPushResult toSingle(GetuiMessage getuiMessage, String clientId) {  
        // 获取消息模板  
        TransmissionTemplate template = PushTemplate.getTransmissionTemplateWith3rdNotifyInfoAndAPNPayload(getuiMessage.getMessageTitle(),  
                getuiMessage.getMessageContent(), "+1", getuiMessage);  
        // 制作消息  
        SingleMessage message = new SingleMessage();  
        message.setData(template);  
        message.setOffline(true);// 设置消息离线,并设置离线时间  
        message.setOfflineExpireTime(72 * 3600 * 1000); // 离线有效时间,单位为毫秒,可选  
//      message.setPriority(1);// 优先级  
//      message.setPushNetWorkType(0); // 判断客户端是否wifi环境下推送。1为仅在wifi环境下推送,0为不限制网络环境,默认不限  
        // 生成接收人  
        Target target = new Target();  
        target.setAppId(GetuiConfig.me.getAppId());  
        target.setClientId(clientId);  
        // 发送消息  
        IPushResult ret = GetuiConfig.me.getPush().pushMessageToSingle(message, target);  
        GetuiConfig.logger.info(GetuiConfig.logger.getName() + JSON.toJSONString(ret));  
        return ret;  
    }  

    /**  
     * 获取同时有Android第三方推送及IOS推送功能的很透传消息  
     *   
     * @param title       标题  
     * @param body        正文  
     * @param badge       IOS的角标数  
     * @param customParam 自定义属性  
     * @return  
     */  
    public static TransmissionTemplate getTransmissionTemplateWith3rdNotifyInfoAndAPNPayload(String title, String body, String badge,  
            Map<String, String> customParam) {  
        TransmissionTemplate template = new TransmissionTemplate();  

        // 设置APPID与APPKEY  
        template.setAppId(GetuiConfig.me.getAppId());  
        template.setAppkey(GetuiConfig.me.getAppKey());  

        // 透传消息设置,1为强制启动应用,客户端接收到消息后就会立即启动应用;2为等待应用启动  
        template.setTransmissionType(2);  
        template.setTransmissionContent(JSON.toJSONString(customParam)); // 透传内容  

        // 第三方厂商推送  
        template.set3rdNotifyInfo(get3rdNotifyInfo(title, body, customParam));  

        // 针对IOS,设置APNs  
        template.setAPNInfo(getAPNPayload(title, body, badge, customParam)); // ios消息推送  
        return template;  
    }  

    /**  
     * 第三方厂商通知  
     *   
     * @param title   标题  
     * @param content 正文  
     * @param payload 附带属性  
     * @return  
     */  
    private static Notify get3rdNotifyInfo(String title, String content, Map<String, String> payload) {  
        Notify notify = new Notify();  
        notify.setTitle(title);  
        notify.setContent(content);  
        notify.setType(Type._intent);  
        notify.setIntent(GetuiConfig.me.getIntent(title,content,payload));  
        notify.setPayload(JSON.toJSONString(payload));  
        return notify;  
    }  
    /**  
     * IOS的APNs消息  
     *   
     * @param title  
     * @param body  
     * @param badge  
     * @param customMsg  
     * @return  
     */  
    private static APNPayload getAPNPayload(String title, String body, String badge, Map<String, String> customMsg) {  
        APNPayload payload = new APNPayload();  
        // 在已有数字基础上加1显示,设置为-1时,在已有数字上减1显示,设置为数字时,显示指定数字  
        if (badge != null && badge.trim().length() > 0) {  
            payload.setAutoBadge(badge);  
        }  
        payload.setContentAvailable(1);  
        // ios 12.0 以上可以使用 Dictionary 类型的 sound  
        payload.setSound("default");  
//      payload.setCategory("$由客户端定义");  
        if (customMsg != null) {  
            for (Entry<String, String> enty : customMsg.entrySet()) {  
                payload.addCustomMsg(enty.getKey(), enty.getValue());  
            }  
        }  
//      payload.setAlertMsg(new APNPayload.SimpleAlertMsg("helloCCCC"));//简单模式APNPayload.SimpleMsg  
        payload.setAlertMsg(getDictionaryAlertMsg(title, body)); // 字典模式使用APNPayload.DictionaryAlertMsg  

//      // 设置语音播报类型,int类型,0.不可用 1.播放body 2.播放自定义文本  
//      payload.setVoicePlayType(2);  
//      // 设置语音播报内容,String类型,非必须参数,用户自定义播放内容,仅在voicePlayMessage=2时生效  
//      // 注:当"定义类型"=2, "定义内容"为空时则忽略不播放  
//      payload.setVoicePlayMessage("定义内容");  
//  
//      // 添加多媒体资源  
//      payload.addMultiMedia(new MultiMedia().setResType(MultiMedia.MediaType.pic).setResUrl("资源文件地址").setOnlyWifi(true));  

        return payload;  
    }  

    /**  
     * IOS通知提示样式  
     *   
     * @param title  
     * @param body  
     * @return  
     */  
    private static APNPayload.DictionaryAlertMsg getDictionaryAlertMsg(String title, String body) {  
        APNPayload.DictionaryAlertMsg alertMsg = new APNPayload.DictionaryAlertMsg();  
        alertMsg.setBody(body);  
//      alertMsg.setActionLocKey("显示关闭和查看两个按钮的消息");  
//      alertMsg.setLocKey("loc-key1");  
//      alertMsg.addLocArg("loc-ary1");  
//      alertMsg.setLaunchImage("调用已经在应用程序中绑定的图形文件名");  
        // iOS8.2以上版本支持  
        alertMsg.setTitle(title);  
//      alertMsg.setTitleLocKey("自定义通知标题");  
//      alertMsg.addTitleLocArg("自定义通知标题组");  
        return alertMsg;  
    }  

    /**  
     * 需要使用iOS语音传输,请使用VoIPPayload代替APNPayload【未测试】  
     *  
     *   
     * @return  
     */  
    private static VoIPPayload getVoIPPayload() {  
        //TODO 未测试,未开发完成  
        VoIPPayload payload = new VoIPPayload();  
        JSONObject jo = new JSONObject();  
        jo.put("key1", "value1");  
        payload.setVoIPPayload(jo.toString());  
        return payload;  
    }  

public class GetuiMessage extends HashMap<String, String> {  

    /**  
     *   
     */  
    private static final long serialVersionUID = -5993986890576211345L;  

    private final String messageTitle = "messageTitle";  
    private final String messageContent = "messageContent";  
    private final String messageType = "messageType";  

    /**  
     * 生成推送消息  
     *   
     * @param typeEnum    消息类型  
     * @param customParam 消息内容参数和消息点击需要的参加共享相同参数  
     */  
    public GetuiMessage(MessageType typeEnum, Map<String, String> customParam) {  
        if (customParam != null && customParam.size() > 0) {  
            this.putAll(customParam);  
        }  
        // 把优先级高的Key放在后面,即遍在customParam有重复的KEY,也不会影响。  
        this.put(messageTitle, typeEnum.getTitle());  
        this.put(messageType, typeEnum.getCode());  
        this.put(messageContent, typeEnum.getContent(customParam));  
    }  

参考(Push推送使用指南):https://ask.dcloud.net.cn/article/35622

17 关注 分享
w***@163.com BJ_Q 老哥教教我 这下真的舒服了 4***@qq.com 左右摇摆 1***@qq.com SimpleJalon 1***@qq.com 1***@qq.com 9***@qq.com Unlimited_S y***@163.com 2***@qq.com 4***@qq.com 2***@qq.com yyf

要回复文章请先登录注册

1***@qq.com

1***@qq.com

回复 y***@wellview.com.cn :
问题解决了么?
2021-03-17 14:12
1***@qq.com

1***@qq.com

回复 xiaoliao998 :
你解决这个问题么?
2021-03-17 14:03
hhr01

hhr01

建议大家有难解决的问题不要浪费时间,直接找客服咨询解决。
2020-12-25 11:14
hhr01

hhr01

1.测试在线推送 即APP打开 在线走个推通道
服务端建议使用透传模板 透传消息内容transmissionContent()设置为一下Json格式

{title:"标题",content:"内容",payload:"自定义数据"}

时 会作为普通推送通知处理,在系统通知栏创建消息,点击消息激活APP触发客户端"click"事件
//监听系统通知栏消息点击事件

plus.push.addEventListener('click', function(msg){
//处理点击消息的业务逻辑代码
}, false);

客户端可在click回调里可通过msg.title获取标题、msg.content获取内容、msg.payload获取数据

2.在线/离线推送 在线走个推通道 离线走厂商通道(前提是厂商通道已经配置好)
为兼容华为 小米 oppo vivo 魅族五大厂商 服务端必须使用透传模板+notify

app打开(即cid在线)走个推通道下发透传消息 方法流程同上1

app后台进程杀死(即cid离线)走厂商通道下发系统通知 intent按照示例替换component里的包名和自定义数据S.payload的值
客户端点击消息 打开app主页面 在click回调方法里可以拿到intent自定义数据
具体模板示例代码参考:https://ask.dcloud.net.cn/article/35622
透传消息文档(java):https://www.dcloud.io/docs/a/unipush/java.pdf
2020-12-25 11:12
hws007

hws007

回复 被梦想绊倒 :
分亨一下
2020-12-24 11:46
hhr01

hhr01

回复 t***@163.com :
你好,请问官方文档哪里说明了,可否给出一下
2020-12-24 11:14
DCloud_uniCloud_JSON

DCloud_uniCloud_JSON

亲们可以参考含离线厂家推送、消息中心UI、已读未读处理、本地&同步远程的角标处理、支持苹果、小米、华为和部分oppo手机的厂家离线推送角标设置的插件:[https://ext.dcloud.net.cn/plugin?id=1680](https://ext.dcloud.net.cn/plugin?id=1680)
2020-12-07 20:44
xiaoliao998

xiaoliao998

回复 y***@wellview.com.cn :
一摸一样的问题,糟心
2020-12-04 21:47
xiaoliao998

xiaoliao998

回复 y***@wellview.com.cn :
解决了吗?遇到同样的问题,头疼死了
2020-12-04 21:35
westgogo

westgogo

所以说官方文档坑的一逼,自己设计的系统,自己都不说清楚,非要让开发人员去踩这些坑,浪费N多人时间做这些无用功。
2020-11-11 09:49