推送之手机推送

501 阅读10分钟
 

推送

网页推送,是指将经过整理的信息资源以网页的形式迅速转发至用户的界面,实现用户的多

层次需求,使得用户能够自己设定所需要的信息频道,并直接在用户端接收定制信息的实现

方式。

手机推送

内容

手机推送服务是指服务器定向将信息实时送达手机的服务。与常见的轮询方式(伪推送)

相比区别主要在于两点,一是否长联网,二是到达实时性。推送服务是长联网的,一般到达

手机的延迟在0.1-0.5秒左右,而轮询方式(伪推送)不是长联网的,达到延迟时间则根据轮

询时间的不同为1-10分钟,也有延迟1小时或一天的情况。一般来说,自黑莓,苹果和安卓

采用标准长连接推送方式后,手机推送服务就特指能够实时到达的形式。

手机推送服务的原理很简单,就是通过建立一条手机与服务器的连接链路,当有消息需要

发送到手机时,通过此链路发送即可。

** 推送服务的使用流程虽然略有差别但是大致都和 iOS的APNs 相似:**

1、首先是应用程序注册消息推送。

2、 iOS 向 APNs Server 取得deviceToken。应用程序接受deviceToken。

3、应用程序将deviceToken发送给PUSH服务端程序。

4、 服务端程序向APNs服务发送消息。

5、APNs服务将消息发送给iPhone应用程序。

实现方式

1、Android 推送

方案1、使用C2DM服务(Google Cloud Messaging)

简介:Google推出的云消息服务,即第二代的G2DM。

优点:Google提供的服务、原生、简单,无需实现和部署服务端。

缺点:Android版本限制(必须大于2.2版本),该服务在国内不够稳定、需要用户绑定Goo

gle帐号,受限于Google。

方案2、使用XMPP协议(Openfire + Spark + Smack)

简介:基于XML协议的通讯协议,前身是Jabber,已由IETF国际标准化组织完成了标准化工作。

优点:协议成熟、强大、可扩展性强、主要应用于许多聊天系统中,且已有开源的Java版的开发实例androidpn。

缺点:协议较复杂、冗余(基于XML)、费流量、费电,部署硬件成本高。

方案3、使用MQTT协议

简介:轻量级的、基于代理的“发布/订阅”模式的消息传输协议。

优点:协议简洁、小巧、可扩展性强、省流量、省电,应用到企业领域,且已有C++版的服务端组件rsmb。

缺点:不够成熟、实现较复杂、服务端组件 rsmb 不开源,部署硬件成本较高。

方案4、使用第三方推送服务

简介:通过嵌入SDK使用第三方提供的推送服务,主流的有百度云推送,极光推送,智游推送,Urban Airship,个推,PUBNUB,蝴蝶等。

优点:稳定,成熟,节省开发和探索时间,相对自己开发成本低,推送管理界面及统计程序完善。

缺点:有程序嵌入顾虑 [2]

2、IOS推送

推荐使用APNS服务,稳定,方便,美中不足是没有推送到达的回执和统计,不方便产品运营。如对此方面有需求可以使用极光推送,个推蝴蝶等第三方推送服务解决。

3、Win-Phone推送

使用MPNS(Microsoft 推送通知服务),相应速度不错,但推送不带状态,很多功能无法实现。

本次使用第三方推送极光推送

极光推送官网:

www.jiguang.cn/




引入依赖:

  <!-- 极光推送 -->
        <dependency>
            <groupId>cn.jpush.api</groupId>
            <artifactId>jpush-client</artifactId>
            <version>3.4.8</version>
        </dependency>
        <dependency>
            <groupId>org.msgpack</groupId>
            <artifactId>msgpack</artifactId>
            <version>0.6.12</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>





实现代码:


 private final static String appKey = "5796fd6751ffd45d197d3dc6";

    private final static String masterSecret = "d164a42ecd9070137d3b8bd7";

    private static JPushClient jPushClient = new JPushClient(masterSecret, appKey);

   /* /**
     * 推送给设备标识参数的用户
     *
     * @param registrationId     设备标识
     * @param notification_title 通知内容标题
     * @param msg_title          消息内容标题
     * @param msg_content        消息内容
     * @param extrasparam1       扩展字段1
     * @param extrasparam2       扩展字段2
     * @return 0推送失败,1推送成功

    public static int sendToRegistrationId(String registrationId, String notification_title, String msg_title, String msg_content, String extrasparam1, String extrasparam2) {
        int result = 0;
        try {
            PushPayload pushPayload = JpushClientUtil.buildPushObject_all_registrationId_alertWithTitle(registrationId, notification_title, msg_title, msg_content, extrasparam1, extrasparam2);
            System.out.println(pushPayload);
            PushResult pushResult = jPushClient.sendPush(pushPayload);
            System.out.println(pushResult);
            if (pushResult.getResponseCode() == 200) {
                result = 1;
            }
        } catch (APIConnectionException e) {
            e.printStackTrace();

        } catch (APIRequestException e) {
            e.printStackTrace();
        }

        return result;
    }
     */
    /**
     * 发送给安卓指定用户
     *
     * @param notification_title 通知内容标题
     * @param msg_title          消息内容标题
     * @param msg_content        消息内容
     * @param extrasparam        附加参数
     * @param alias              推送别名
     * @return 0推送失败,1推送成功
     */
    public static int sendToOneAndroid(String notification_title, String msg_title, String msg_content, String extrasparam, String alias) {
        int result = 0;
        try {
            PushPayload pushPayload = JpushClientUtil.buildPushObject_android_all_alertWithTitle(notification_title, msg_title, msg_content, extrasparam, null, alias);
            System.out.println(pushPayload);
            PushResult pushResult = jPushClient.sendPush(pushPayload);
            System.out.println(pushResult);
            if (pushResult.getResponseCode() == 200) {
                result = 1;
            }
        } catch (APIConnectionException e) {
            e.printStackTrace();
        } catch (APIRequestException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }

    /**
     * 发送给所有安卓用户
     *
     * @param notification_title 通知内容标题
     * @param msg_title          消息内容标题
     * @param msg_content        消息内容
     * @return 0推送失败,1推送成功
     */
    public static int sendToAllAndroid(String notification_title, String msg_title, String msg_content, String extrasparam) {
        int result = 0;
        try {
            PushPayload pushPayload = JpushClientUtil.buildPushObject_android_all_alertWithTitleAll(notification_title, msg_title, msg_content, extrasparam);
            System.out.println(pushPayload);
            PushResult pushResult = jPushClient.sendPush(pushPayload);
            System.out.println(pushResult);
            if (pushResult.getResponseCode() == 200) {
                result = 1;
            }
        } catch (Exception e) {

            e.printStackTrace();
        }

        return result;
    }
      private static PushPayload buildPushObject_android_all_alertWithTitle(String notification_title, String msg_title, String msg_content, String extrasparam, String type, String value) {
        System.out.println("----------buildPushObject_android_registrationId_alertWithTitle");
        return PushPayload.newBuilder()
                //指定要推送的平台,all代表当前应用配置了的所有平台,也可以传android等具体平台
                .setPlatform(Platform.android())
                //指定推送的接收对象,all代表所有人,也可以指定已经设置成功的tag或alias或该应应用客户端调用接口获取到的registration id
                //根据别名推送
                .setAudience(Audience.alias(value))

                //jpush的通知,android的由jpush直接下发,iOS的由apns服务器下发,Winphone的由mpns下发
                .setNotification(Notification.newBuilder()
                        //指定当前推送的android通知
                        .addPlatformNotification(AndroidNotification.newBuilder()
                                .setAlert(msg_content)
                                .setTitle(msg_title)
                                //此字段为透传字段,不会显示在通知栏。用户可以通过此字段来做一些定制需求,如特定的key传要指定跳转的页面(value)
                                .addExtra("type", extrasparam)
                                .build())
                        .build()
                )
                //Platform指定了哪些平台就会像指定平台中符合推送条件的设备进行推送。 jpush的自定义消息,
                // sdk默认不做任何处理,不会有通知提示。建议看文档http://docs.jpush.io/guideline/faq/的
                // [通知与自定义消息有什么区别?]了解通知和自定义消息的区别
                .setMessage(Message.newBuilder()
                        .setMsgContent(msg_content)
                        .setTitle(msg_title)
//                        .addExtra("message extras key",extrasparam)
                        .addExtra("status", extrasparam)
                        .build())

                .setOptions(Options.newBuilder()
                        //此字段的值是用来指定本推送要推送的apns环境,false表示开发,true表示生产;对android和自定义消息无意义
                        .setApnsProduction(false)
                        //此字段是给开发者自己给推送编号,方便推送者分辨推送记录
                        .setSendno(1)
                        //此字段的值是用来指定本推送的离线保存时长,如果不传此字段则默认保存一天,最多指定保留十天,单位为秒
                        .setTimeToLive(86400)
                        .build())
                .build();
    }

    private static PushPayload buildPushObject_android_all_alertWithTitleAll(String notification_title, String msg_title, String msg_content, String extrasparam) {
        System.out.println("----------buildPushObject_android_registrationId_alertWithTitle");
        return PushPayload.newBuilder()
                //指定要推送的平台,all代表当前应用配置了的所有平台,也可以传android等具体平台
                .setPlatform(Platform.android())
                //指定推送的接收对象,all代表所有人,也可以指定已经设置成功的tag或alias或该应应用客户端调用接口获取到的registration id
//               //Audience设置为all,说明采用广播方式推送,所有用户都可以接收到
                .setAudience(Audience.all())

                //jpush的通知,android的由jpush直接下发,iOS的由apns服务器下发,Winphone的由mpns下发
                .setNotification(Notification.newBuilder()
                        //指定当前推送的android通知
                        .addPlatformNotification(AndroidNotification.newBuilder()
                                .setAlert(msg_content)
                                .setTitle(msg_title)

                                //此字段为透传字段,不会显示在通知栏。用户可以通过此字段来做一些定制需求,如特定的key传要指定跳转的页面(value)
                                .addExtra("type", extrasparam)
                                .build())
                        .build()
                )
                //Platform指定了哪些平台就会像指定平台中符合推送条件的设备进行推送。 jpush的自定义消息,
                // sdk默认不做任何处理,不会有通知提示。建议看文档http://docs.jpush.io/guideline/faq/的
                // [通知与自定义消息有什么区别?]了解通知和自定义消息的区别
                .setMessage(Message.newBuilder()
                        .setMsgContent(msg_content)
                        .setTitle(msg_title)
                        .addExtra("status", extrasparam)
                        .build())

                .setOptions(Options.newBuilder()
                        //此字段的值是用来指定本推送要推送的apns环境,false表示开发,true表示生产;对android和自定义消息无意义
                        .setApnsProduction(false)
                        //此字段是给开发者自己给推送编号,方便推送者分辨推送记录
                        .setSendno(1)
                        //此字段的值是用来指定本推送的离线保存时长,如果不传此字段则默认保存一天,最多指定保留十天,单位为秒
                        .setTimeToLive(86400)
                        .build())
                .build();
    }

    /*private static PushPayload buildPushObject_ios_all_alertWithTitle(String notification_title, String msg_title, String msg_content, String extrasparam) {
        System.out.println("----------buildPushObject_ios_registrationId_alertWithTitle");
        return PushPayload.newBuilder()
                //指定要推送的平台,all代表当前应用配置了的所有平台,也可以传android等具体平台
                .setPlatform(Platform.ios())
                //指定推送的接收对象,all代表所有人,也可以指定已经设置成功的tag或alias或该应应用客户端调用接口获取到的registration id
                .setAudience(Audience.all())
                //jpush的通知,android的由jpush直接下发,iOS的由apns服务器下发,Winphone的由mpns下发
                .setNotification(Notification.newBuilder()
                        //指定当前推送的android通知
                        .addPlatformNotification(IosNotification.newBuilder()
                                //传一个IosAlert对象,指定apns title、title、subtitle等
                                .setAlert(notification_title)
                                //直接传alert
                                //此项是指定此推送的badge自动加1
                                .incrBadge(1)
                                //此字段的值default表示系统默认声音;传sound.caf表示此推送以项目里面打包的sound.caf声音来提醒,
                                // 如果系统没有此音频则以系统默认声音提醒;此字段如果传空字符串,iOS9及以上的系统是无声音提醒,以下的系统是默认声音
                                .setSound("sound.caf")
                                //此字段为透传字段,不会显示在通知栏。用户可以通过此字段来做一些定制需求,如特定的key传要指定跳转的页面(value)
                                .addExtra("iosNotification extras key", extrasparam)
                                //此项说明此推送是一个background推送,想了解background看:http://docs.jpush.io/client/ios_tutorials/#ios-7-background-remote-notification
                                // .setContentAvailable(true)

                                .build())
                        .build()
                )
                //Platform指定了哪些平台就会像指定平台中符合推送条件的设备进行推送。 jpush的自定义消息,
                // sdk默认不做任何处理,不会有通知提示。建议看文档http://docs.jpush.io/guideline/faq/的
                // [通知与自定义消息有什么区别?]了解通知和自定义消息的区别
                .setMessage(Message.newBuilder()
                        .setMsgContent(msg_content)
                        .setTitle(msg_title)
                        .addExtra("message extras key", extrasparam)
                        .build())

                .setOptions(Options.newBuilder()
                        //此字段的值是用来指定本推送要推送的apns环境,false表示开发,true表示生产;对android和自定义消息无意义
                        .setApnsProduction(false)
                        //此字段是给开发者自己给推送编号,方便推送者分辨推送记录
                        .setSendno(1)
                        //此字段的值是用来指定本推送的离线保存时长,如果不传此字段则默认保存一天,最多指定保留十天,单位为秒
                        .setTimeToLive(86400)
                        .build())
                .build();
    }
*/
    public static void main(String[] args) {

        if(JpushClientUtil.sendToAllAndroid("推送给所有Android用户","典韦的推送","测试推送消息","101")==1)
        {
            System.out.println("推送给所有" +
                    "Android用户success");
        }
       /* if (JpushClientUtil.sendToOneAndroid("推送给指定Android用户", "典韦的推送", "测试推送消息", "102", "Dianwei20010922") == 1) {
            System.out.println("推送给指定Android用户success");
        }*/
    }
}

然后这个工具类中提供了一个main方法用来进行推送测试。

首先将上面工具类中的Appkey和secret修改为Jpush开发者平台上应用对应的数据。

然后先打开推送给所有安卓用户的测试方法,运行

{"msg_id":18100019379833432,"sendno":1,"statusCode":0}
推送给所有Android用户success

Process finished with exit code 0


d85f2633589eed361f70956e6621c629.jpg