呢
  • 发布:2019-04-27 17:41
  • 更新:2022-07-14 17:54
  • 阅读:35845

消息 推送:uni-app开发之unipush推送踩坑填坑之旅

分类:uni-app

最近需要开发app,经过多方对比,最终选择了使用dcloud的uni-app,一套代码可以编译七个平台,最主要就是相比于apicloud来说支持本地打包,减少了很多可能会带来的限制。
也就想着,它最大的诟病是说社区不活跃,可是社区氛围也是需要大家一块积极贡献的,那么我们团队加进来也给他增加一点活跃度。

做app免不了会需要推送,从服务器主动给客户端发信息联系,这是客户端app相对来说非常大的一个优势。

刚刚把uni-app在安卓端的推送走通,此处记录一下经验以方便后来者参考。

1. 开通UniPush推送服务

UniPush仅支持uni-app类型项目,其它类型项目暂不支持
点此查看如何开通UniPush推送服务

在Hbuilder中修改mainfest.json文件配置

勾选DCloud UniPush,然后点击配置按钮会进入uniPush的后端配置,需要先认证,认证通过后,可以在我创建的应用列表中查看自己当前的应用。如果有多个项目,此处可以根据列表中的App_id和本地的appid关联查看
https://dev.dcloud.net.cn/#/pages/app/list


点击当前项目,进入对应项目的管理页面,选择上方uniPush选项,点击厂商推送设置,填写自己想要指定的包名及根据本地证书生成的签名信息(如果要使用官方的证书,那就按提示填写官方签名信息)

配置完可进入uniPush的“通知消息”测试页面

自定义基座

要想实现推送功能,需要先自定义基座(因为推送也是需要依赖包名等信息的,官方说过,推送必须要用自定义基座才行)


选择自定义基座,然后会有弹窗提示

这里可以选择使用公用证书,也可以使用自己之前已经生成的自有证书签名,填写必要的信息,然后选择打包;此处要注意这里填写的包名要和上面unipush管理页面中配置的一样。

填写完成后,点击打包按钮,等待。完成后会在控制台提示

我们按照提示,选择自己之前定义的基座即可。这个时候再点击运行到手机或模拟器,然后在后台测试推送即可

测试推送

进入unipush推送通知的页面创建推送,填写通知标题和通知内容,此处如果有客户端之前运行成功,那么预计人数会不是0人,如果是0人的话确定按钮会无法点击,因为无人可推;即使在目标选择中根据客户端输出的clientid选择了特定用户,手机端也是无法推送的。此处如果不行,就再去检查包名配置和基座选择是否有问题。

因为这个系统就是个推给dcloud的私有部署,所以如果有疑问的方面也可以到个推官方注册一个账号,下载demo试试,增加一点成就感。并且后续的开发sdk、文档等都可以根据个推的做。

服务端推送快速入门

我们在本地建一个maven项目,在pom.xml的dependencies中增加一个推送sdk的依赖包配置

<dependency>  
    <groupId>com.gexin.platform</groupId>  
    <artifactId>gexin-rp-sdk-http</artifactId>  
    <version>4.1.0.1</version>  
</dependency>

如果下载有问题,可以在project的下层添加一个库位置

<repositories>  
    <repository>  
        <id>getui-nexus</id>  
        <url>http://mvn.gt.igexin.com/nexus/content/repositories/releases/</url>  
    </repository>  
 </repositories>

然后建测试类如下,把其中的appid、appkey、masterSecret换成自己的,url不用换;
经过测试推测,虽然在unipush中有私有部署系统,但是推送的消息队列还是在个推云。大概是OEM

import com.gexin.rp.sdk.base.IPushResult;  
import com.gexin.rp.sdk.base.impl.AppMessage;  
import com.gexin.rp.sdk.http.IGtPush;  
import com.gexin.rp.sdk.template.LinkTemplate;  

import java.io.IOException;  
import java.util.ArrayList;  
import java.util.List;  

public class AppPush {  

    //定义常量, appId、appKey、masterSecret 采用本文档 "第二步 获取访问凭证 "中获得的应用配置  
    private static String appId = "你的appid";  
    private static String appKey = "你的appkey";  
    private static String masterSecret = "你的masterSecret";  
    private static String url = "http://sdk.open.api.igexin.com/apiex.htm";  

    public static void main(String[] args) throws IOException {  

        IGtPush push = new IGtPush(url, appKey, masterSecret);  

        // 定义"点击链接打开通知模板",并设置标题、内容、链接  
        LinkTemplate template = new LinkTemplate();  
        template.setAppId(appId);  
        template.setAppkey(appKey);  
        template.setTitle("你好你好");  
        template.setText("哦,好吧");  
        template.setUrl("http://getui.com");  

        List<String> appIds = new ArrayList<String>();  
        appIds.add(appId);  

        // 定义"AppMessage"类型消息对象,设置消息内容模板、发送的目标App列表、是否支持离线发送、以及离线消息有效期(单位毫秒)  
        AppMessage message = new AppMessage();  
        message.setData(template);  
        message.setAppIdList(appIds);  
        message.setOffline(true);  
        message.setOfflineExpireTime(1000 * 600);  

        IPushResult ret = push.pushMessageToApp(message);  
        System.out.println(ret.getResponse().toString());  
    }  
}

透传消息

考虑到推送通知只在android端可以使用,为了以后ios推送少改,所以此处我们也使用透传消息推送;又知透传消息的格式当满足

t.setTransmissionContent("{title:\"标题\",content:\"内容\",payload:\"自定义数据\"}");

时,会在安卓端自动转为通知消息,所以我们此处就按这种方式推送透传消息。
其中payload的值既可以是字符串,又可以是对象;这里的示例数据我写的是字符串,但实际使用时可以修改格式来符合自身业务逻辑的处理,比如

{title:"标题",content:"内容",payload:{type:1,fId:1}}

对于代码的修改主要是要改动消息模板,即将上面的LinkTemplate改成TransmissionTemplate,
代码如下:

public static void main(String[] args) throws IOException {  

        IGtPush push = new IGtPush(url, appKey, masterSecret);  

        TransmissionTemplate t = new TransmissionTemplate();  
        t.setAppId(appId);  
        t.setAppkey(appKey);  
        t.setTransmissionContent("{title:\"标题\",content:\"内容\",payload:\"自定义数据\"}");  
        t.setTransmissionType(1);  

        // 定义"点击链接打开通知模板",并设置标题、内容、链接  
//        LinkTemplate template = new LinkTemplate();  
//        template.setAppId(appId);  
//        template.setAppkey(appKey);  
//        template.setTitle("你好你好");  
//        template.setText("哦,好吧");  
//        template.setLogoUrl("");  
//        template.setUrl("http://getui.com");  

        List<String> appIds = new ArrayList<String>();  
        appIds.add(appId);  

        // 定义"AppMessage"类型消息对象,设置消息内容模板、发送的目标App列表、是否支持离线发送、以及离线消息有效期(单位毫秒)  
        AppMessage message = new AppMessage();  
        message.setData(t);  
        message.setAppIdList(appIds);  
        message.setOffline(true);  
        message.setOfflineExpireTime(1000 * 600);  

        IPushResult ret = push.pushMessageToApp(message);  
        System.out.println(ret.getResponse().toString());  
}

怎么监听通知点击事件

注意条件编译

// #ifdef APP-PLUS  
            // #ifdef APP-PLUS  
            plus.push.addEventListener('click', function(msg) {  
                console.log(JSON.stringify(msg.payload.fId))  
                switch (msg.payload.type) {  
                    case 1:  
                        uni.navigateTo({  
                            url: '/pages/listDetail/alarmDetail?id=' + msg.payload.fId,  
                            success: res => {},  
                            fail: () => {},  
                            complete: () => {}  
                        });  
                        break;  
                    case 2:  
                        uni.navigateTo({  
                            url: '/pages/workStation/inspection/deal/deal?inspectId=' + msg.payload.fId  
                        })  
                        break;  
                    case 3:  
                        uni.navigateTo({  
                            url: '/pages/listDetail/orderDetail?oid=' + msg.payload.fId,  
                            success: res => {},  
                            fail: () => {},  
                        })  
                        break;  
                    case 4:  
                        uni.navigateTo({  
                            url: '/pages/auth/check?authId=' + msg.payload.fId,  
                            success: res => {},  
                            fail: () => {},  
                        })  
                        break;  
                }  
            }, false);  

            //监听接收透传消息事件    
            plus.push.addEventListener('receive', function(msg) {  
                console.log(JSON.stringify(msg))  
                // plus.nativeUI.alert(msg)  
                //处理透传消息的业务逻辑代码    
            }, false);  
            // #endif

本地编译

作为专业的客户端开发人员,最好还是在本地有完整的编译环境。这也是我们在dcloud和apicloud之间选择当前技术栈的原因。

为了简单起见,可以把官方提供的实例项目HBuilder-Hello先在本地打包,然后用官方实例的壳,将里面h5的一些生成文件替换。此处操作流程如下:

  1. 生成本地打包App资源

  2. 将生成的资源放进实例项目app\src\main\assets\apps文件夹下,将之前的Hello H5删掉即可,
    然后将此路径下的dcloud_control.xml中的appid的值改为apps下一层即www上一层文件夹的名称

  • 此时已经可以打包成app并且正常打开,但是还不能推送 *
  1. 修改src/main/java文件夹下的包名为自己之前填写的包名,修改src/main下AndroidManifest.xml中package包名,修改AndroidManifest.xml中的推送参数配置

然后debug或打包即可。

问题解答

问:

  1. 请问服务端的代码还是只能用个推的吗,也就是说需要去个推开发者中心去注册账号拿到appid、appkey、masterSecret吗?那么使用uni-push的优势有什么呢?单纯使用个推也能完成推送功能
  2. 如果我想要给特定的某些/单个用户发消息,之前尝试了可以使用cid进行区别发送,我看你的教程里面没有使用cid,所以我想要知道在服务端代码上如何实现

答:

个推只是其中一个方案,你如果用jpush之类的,社区也有其他人做的教程;不过这个毕竟是dcloud官方给的推荐方案,所以没什么特殊情况,我们还是选用这个。

uni-push集成了个推,unipush的管理界面其实就是用的个推的系统,甚至据我推测,推送服务也是用的个推云。
不过不用取个推再注册,按unipush中的账号使用即可。

单个推送部分代码示例:

// 指定向哪儿推  
Target target = new Target();  
target.setAppId(appId);  
target.setClientId(cId);  

IGtPush push = new IGtPush(url, appKey, masterSecret);  
IPushResult ret = push.pushMessageToSingle(message, target);
15 关注 分享
DCloud_云服务_Mal 7***@qq.com 香蕉不是笨啦啦 逐鹿实验室 1***@qq.com skysowe DCloud_iOS_XHY HealerLZH 4***@qq.com 啊啵吃d 9***@qq.com 旋转的刘艹艹 6***@qq.com 凯levs 1***@qq.com

要回复文章请先登录注册

jonychen1

jonychen1

我最近也在寻找相关的第三方,最后选中了goeasy,前端是基于js开发的所以就不局限于只支持uniapp,特别是技术支持非常给力啊,如果有需要的也可以去了解一下,地址:https://www.goeasy.io/
2022-07-14 17:54
missfei

missfei

回复 呢 :
是内容字符格式的问题,引不起 click
2022-04-25 11:42
呢

(作者)

回复 missfei :
在click内第一行写输出看了吗
2022-04-18 14:13
missfei

missfei

我receive 能收到消息,我创建了通知栏消息, 但是点击的时候,监听的 click 事件没啥用呢, 啥情况啊?谢谢
2022-03-30 22:23
呢

(作者)

回复 小李子l1999 :
嗯,虽然客户端也可以生成,但是最好还是由服务器推
2021-08-31 14:05
呢

(作者)

嗯,虽然客户端也可以生成,但是最好还是由服务器推
2021-08-31 14:05
小李子l1999

小李子l1999

回复 呢 :
您好,就是现在是要通知不同的用户,通知时间取决于用户有未读消息的时候进行推送,推送的内容:'您有xx条未读消息' 这个应该要用个推的服务端推送吧?然后客户端只负责接收。
2021-08-24 14:24
呢

(作者)

回复 小李子l1999 :
没看明白你的意思,是在后台部分的逻辑还是手机端的,你是想要本地生成通知?
2021-08-23 17:51
小李子l1999

小李子l1999

你好,请问如何通过后台返回的数据然后再推送内容?
2021-08-21 14:22
呢

(作者)

回复 凌风浮云S :
在App.vue的onLaunch()里面增加事件监听
示例:

// #ifdef APP-PLUS
plus.push.addEventListener('click', function(msg) {
console.log(JSON.stringify(msg.payload.fId))
switch (msg.payload.type) {
case 1:
uni.navigateTo({
url: '/pages/listDetail/alarmDetail?id=' + msg.payload.fId,
success: res => {},
fail: () => {},
complete: () => {}
});
2021-06-26 10:59