极光消息推送服务器端开发实现推送

以前一直使用的极光的手动输入推送内容然后推送到客户端,今天遇到了推送频率比较高且比较有规律的内容,比如事实天气。这样就需要用我们自己的服务器来自动生成推送内容了。

在官方的SDK文档中找了半天,终于找到了有点类似的接口了,进去先看看:http://docs.jpush.cn/pages/viewpage.action?pageId=2228302

可以看到,上面两句话很醒目,我们看看它封装的REST API是个什么东西,再点进去看看

上面两句话读了一下,大笑看来我们的运气还不错,这个应该就是了。

好了我们进入上面的Java开发部分:https://github.com/jpush/jpush-api-java-client

进去看了半天,大概明白意思了,已经帮助我们封装好了,现在我们只需要下载jar包和它提供的实例文档。

进去后发现又对RESI API进行了更详细的说明,比如参数、频率限制等。

好吧,我们看看推送消息和通知,如下图点击进入

进去之后就看到了真真需要的api接口了,这里有各个方法和参数的说明。如果有的朋友还觉得看不懂,简单,直接下载示例代码(抄袭谁不会啊偷笑

我下载官方示例代码,新建立了一个项目如下:

消息发送端代码:

 

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片

  1. package com.meritit.tuisong.service;
  2. import java.util.HashMap;
  3. import java.util.Map;
  4. import cn.jpush.api.ErrorCodeEnum;
  5. import cn.jpush.api.IOSExtra;
  6. import cn.jpush.api.JPushClient;
  7. import cn.jpush.api.MessageResult;
  8. public class JPushClientExample {
  9.     private static final String appKey =”5d30bebd28335593a13454861″;    //必填,例如466f7032ac604e02fb7bda89
  10.     private static final String masterSecret = “0e0cc80c6f6a4703bec9ed191″;//”13ac09b17715bd117163d8a1”;//必填,每个应用都对应一个masterSecret
  11.     private static JPushClient jpush = null;
  12.     /**
  13.      * 保存离线的时长。秒为单位。最多支持10天(864000秒)。
  14.      * 0 表示该消息不保存离线。即:用户在线马上发出,当前不在线用户将不会收到此消息。
  15.      * 此参数不设置则表示默认,默认为保存1天的离线消息(86400秒)。
  16.      */
  17.     private static long timeToLive =  60 * 60 * 24;
  18.     public static void main(String[] args) {
  19.         /*
  20.          * Example1: 初始化,默认发送给android和ios,同时设置离线消息存活时间
  21.          * jpush = new JPushClient(masterSecret, appKey, timeToLive);
  22.          */
  23.         /*
  24.          * Example2: 只发送给android
  25.          * jpush = new JPushClient(masterSecret, appKey, DeviceEnum.Android);
  26.          */
  27.         /*
  28.          * Example3: 只发送给IOS
  29.          * jpush = new JPushClient(masterSecret, appKey, DeviceEnum.IOS);
  30.          */
  31.         /*
  32.          * Example4: 只发送给android,同时设置离线消息存活时间
  33.          * jpush = new JPushClient(masterSecret, appKey, timeToLive, DeviceEnum.Android);
  34.          */
  35.         jpush = new JPushClient(masterSecret, appKey, timeToLive);
  36.         /*
  37.          * 是否启用ssl安全连接, 可选
  38.          * 参数:启用true, 禁用false,默认为非ssl连接
  39.          */
  40.         //jpush.setEnableSSL(true);
  41.         //测试发送消息或者通知
  42.         testSend();
  43.     }
  44.     private static void testSend() {
  45.         // 在实际业务中,建议 sendNo 是一个你自己的业务可以处理的一个自增数字。
  46.         // 除非需要覆盖,请确保不要重复使用。详情请参考 API 文档相关说明。
  47.         int sendNo = getRandomSendNo();
  48.         String msgTitle = “+;//jpush\”\””;
  49.         String msgContent = “\\&;w\”\”a–【\npush】”;
  50.         /*
  51.          * IOS设备扩展参数,
  52.          * 设置badge,设置声音
  53.          */
  54.         Map<String, Object> extra = new HashMap<String, Object>();
  55.         IOSExtra iosExtra = new IOSExtra(10, “WindowsLogonSound.wav”);
  56.         extra.put(“ios”, iosExtra);
  57.         //对所有用户发送通知, 更多方法请参考文档
  58.         MessageResult msgResult = jpush.sendCustomMessageWithAppKey(sendNo,msgTitle, msgContent);
  59.         //MessageResult msgResult  = jpush.sendNotificationWithAlias(sendNo, “a”, msgTitle, msgContent);
  60.         //覆盖指定msgId的消息,msgId可以从msgResult.getMsgid()获取。
  61.         //MessageResult msgResult = jpush.sendNotificationWithAppKey(sendNo, msgTitle, msgContent, 0, extra,msgResult.getMsgid());
  62.         if (null != msgResult) {
  63.             System.out.println(“服务器返回数据: ” + msgResult.toString());
  64.             if (msgResult.getErrcode() == ErrorCodeEnum.NOERROR.value()) {
  65.                 System.out.println(String.format(“发送成功, sendNo= %s,messageId= %s”,msgResult.getSendno(),msgResult.getMsg_id()));
  66.             } else {
  67.                 System.out.println(“发送失败, 错误代码=” + msgResult.getErrcode() + “, 错误消息=” + msgResult.getErrmsg());
  68.             }
  69.         } else {
  70.             System.out.println(“无法获取数据”);
  71.         }
  72.     }
  73.     public static final int MAX = Integer.MAX_VALUE;
  74.     public static final int MIN = (int) MAX/2;
  75.     /**
  76.      * 保持 sendNo 的唯一性是有必要的
  77.      * It is very important to keep sendNo unique.
  78.      * @return sendNo
  79.      */
  80.     public static int getRandomSendNo() {
  81.         return (int) (MIN + Math.random() * (MAX – MIN));
  82.     }
  83. }

 

执行结果如下:

消息接收端代码:

 

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片

  1. package com.meritit.tuisong.service;
  2. import java.util.List;
  3. import cn.jpush.api.JPushClient;
  4. import cn.jpush.api.receive.ReceiveResult;
  5. public class ReceiveClientExample {
  6.     private static final String appKey =”5d30bebd28335593a13454861″;    //必填,例如466f7032ac604e02fb7bda89
  7.     private static final String masterSecret = “0e0cc80c6f6a4703bec9ed191″;//”13ac09b17715bd117163d8a1”;//必填
  8.     public static void main(String[] args) {
  9.         JPushClient JPushClient = new JPushClient(masterSecret, appKey);
  10.         String msgId = “1236722141”;
  11.         String[] msgIds = {“1236722141″,”910981248″,”911034889”};
  12.         //获取一条
  13.         ReceiveResult receiveResult =  JPushClient.getReceived(msgId);
  14.         if(receiveResult == null){
  15.             System.out.println(“获取receive 数据失败!”+receiveResult);
  16.         }else{
  17.             //gson toJson 之后,NULL值的字段会被过滤掉
  18.             System.out.println(“received result:”+receiveResult.toString());
  19.         }
  20.         // 获取多条
  21.         List<ReceiveResult> receiveResults = JPushClient.getReceiveds(msgIds);
  22.         if(receiveResults == null ){
  23.             System.out.println(“获取receive 数据失败!”);
  24.         }else{
  25.             System.out.println(“成功获取了:”+receiveResults);
  26.         }
  27.     }
  28. }

执行结果:

 

测试已经成功,下面我们来看看源代码是怎么做的,其他的其实只是数据封装,我们来看看关键的一句代码

 

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片

  1. MessageResult msgResult = jpush.sendCustomMessageWithAppKey(sendNo,msgTitle, msgContent);

查看源代码,如下:

 

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片

  1. public MessageResult sendCustomMessageWithAppKey(int sendNo, String msgTitle, String msgContent) {
  2.     CustomMessageParams p = new CustomMessageParams();
  3.     p.setReceiverType(ReceiverTypeEnum.APPKEYS);
  4.     return sendCustomMessage(p, sendNo, msgTitle, msgContent, null, null);
  5. }

发现实际是调用的sendCustomMessage方法

 

 

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片

  1. protected MessageResult sendCustomMessage(CustomMessageParams p, int sendNo, String msgTitle, String msgContent, String msgContentType, Map<String, Object> extra) {
  2.     if (null != msgContentType) {
  3.         p.getMsgContent().setContentType(msgContentType);
  4.     }
  5.     if (null != extra) {
  6.         p.getMsgContent().setExtra(extra);
  7.     }
  8.     return sendMessage(p, sendNo, msgTitle, msgContent);
  9. }

这里进行了空值判断,实际又调用了sendMessage方法

 

 

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片

  1. protected MessageResult sendMessage(MessageParams p, int sendNo, String msgTitle, String msgContent) {
  2.     p.setSendNo(sendNo);
  3.     p.setAppKey(this.getAppKey());
  4.     p.setMasterSecret(this.masterSecret);
  5.     p.setTimeToLive(this.timeToLive);
  6.     p.setSendDescription(this.getSendDescription());
  7.     for (DeviceEnum device : this.getDevices()) {
  8.         p.addPlatform(device);
  9.     }
  10.     if (null != msgTitle) {
  11.         p.getMsgContent().setTitle(msgTitle);
  12.     }
  13.     p.getMsgContent().setMessage(msgContent);
  14.     return sendMessage(p);
  15. }

在这里将参数封装到消息对象中调用sendMessage

 

 

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片

  1. protected MessageResult sendMessage(MessageParams params) {
  2.     return httpClient.sendPush(BaseURL.ALL_PATH, enableSSL, params);
  3. }

再进到sendPush方法中看看,哦,大概明白了,实际上是用的http请求发送消息的。

 

 

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片

  1. public MessageResult sendPush(final String path, final boolean enableSSL, final MessageParams messageParams) {
  2.     MessageResult messageResult = ValidateRequestParams.vidateParams(messageParams);
  3.     if(messageResult != null) return messageResult;
  4.     String pushResult = sendPost(path, enableSSL, parse(messageParams),RequestTypeEnum.PUSH.value(),null);
  5.     return gson.fromJson(pushResult, MessageResult.class);
  6. }

关键看倒数第二行代码

 

 

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片

  1. private String sendPost( String path, final boolean enableSSL, String params,Integer reqeustType,String authCode){
  2.     return sendRequest(path, enableSSL, params, “POST”, reqeustType,authCode);
  3. }

 

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片

  1. private String sendRequest(String path, final boolean enableSSL, String params,String method,Integer reqeustType,String authCode){
  2.     HttpURLConnection conn = null;
  3.     DataOutputStream outStream = null;
  4.     StringBuffer sb = new StringBuffer();
  5.     try {
  6.         if (enableSSL) {
  7.             initSSL();
  8.         }
  9.         URL url = new URL(BaseURL.getUrlForPath(path,enableSSL,reqeustType));
  10.         conn = (HttpURLConnection) url.openConnection();
  11.         conn.setConnectTimeout(DEFAULT_CONNECTION_TIMEOUT);
  12.         conn.setReadTimeout(DEFAULT_SOCKET_TIMEOUT);
  13.         conn.setUseCaches(false);
  14.         conn.setDoOutput(true);
  15.         conn.setRequestMethod(method);
  16.         conn.setRequestProperty(“Connection”, “Keep-Alive”);
  17.         conn.setRequestProperty(“Charset”, CHARSET);
  18.         if(authCode != null && !authCode.isEmpty()){
  19.             conn.setRequestProperty(“Authorization”, authCode);
  20.         }
  21.         if(method.equals(“POST”)){
  22.             byte[] data = params.getBytes(CHARSET);
  23.             conn.setRequestProperty(“Content-Type”, “application/x-www-form-urlencoded”);
  24.             conn.setRequestProperty(“Content-Length”, String.valueOf(data.length));
  25.             outStream = new DataOutputStream(conn.getOutputStream());
  26.             outStream.write(data);
  27.             outStream.flush();
  28.         }
  29.         if (conn.getResponseCode() == 200) {
  30.             logger.info(“Congratulations!The request was successful. response status is 200”);
  31.             InputStream in = conn.getInputStream();
  32.             InputStreamReader reader = new InputStreamReader(in, CHARSET);
  33.             char[] buff = new char[1024];
  34.             int len;
  35.             while ((len = reader.read(buff)) > 0) {
  36.                 sb.append(buff, 0, len);
  37.             }
  38.         } else {
  39.             logger.log(Level.WARNING,”Sorry!The request was fault. response ” +
  40.                     “status = “+conn.getResponseCode()+”,errormsg = “+conn.getHeaderField(0));
  41.             String errmsg = “”;
  42.             if(reqeustType == RequestTypeEnum.RECEIVE.value()){
  43.                 errmsg = ErrorCodeEnum.errorMsg(conn.getResponseCode());
  44.                 errmsg = errmsg == null ? conn.getHeaderField(0) : errmsg;
  45.             }else{
  46.                 errmsg = conn.getHeaderField(0);
  47.             }
  48.             BaseResult result = new BaseResult(errmsg,conn.getResponseCode());
  49.             return result.toString();
  50.         }
  51.     }
  52.     catch (SocketTimeoutException e) {
  53.         logger.log(Level.SEVERE,”God! the server throw SocketTimeout Exception.” +
  54.                 “please check it out the error message:”+e.getMessage());
  55.         BaseResult baseResult = new BaseResult(e.getMessage().toString(),ErrorCodeEnum.CONNECTIONTIMEOUT.value());
  56.         return baseResult.toString();
  57.     }
  58.     catch (ConnectException e) {
  59.         logger.log(Level.SEVERE,”God! the server throw Connect Exception .” +
  60.                 “please check it out the error message:”+e.getMessage());
  61.         BaseResult baseResult = new BaseResult(e.getMessage().toString(),ErrorCodeEnum.CONNECTIONREFUSED.value());
  62.         return baseResult.toString();
  63.     }
  64.     catch (UnknownHostException e) {
  65.         logger.log(Level.SEVERE,”God! the server throw UnknownHost Exception .” +
  66.                 “please check it out the error message:”+e.getMessage());
  67.         BaseResult baseResult = new BaseResult(e.getMessage().toString(),ErrorCodeEnum.CONNECTIONREFUSED.value());
  68.         return baseResult.toString();
  69.     }
  70.     catch (Exception e) {
  71.         logger.log(Level.SEVERE,”God! the server throw exception.” +
  72.                 “please check it out the error message:”+e.getMessage());
  73.         BaseResult baseResult = new BaseResult(e.getMessage().toString(),ErrorCodeEnum.UnknownException.value());
  74.         return baseResult.toString();
  75.     }
  76.     finally {
  77.         if (null != outStream) {
  78.             try {
  79.                 outStream.close();
  80.             } catch (IOException e) {
  81.                 e.printStackTrace();
  82.             }
  83.         }
  84.         if (null != conn) {
  85.             conn.disconnect();
  86.         }
  87.     }
  88.     return sb.toString();
  89. }

学过Android的朋友对这个应该很熟悉吧!比如里面的URL请求地址,看第9行代码

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片

  1. URL url = new URL(BaseURL.getUrlForPath(path,enableSSL,reqeustType));

 

 

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片

  1. public  static String getUrlForPath(final String path,boolean enableSSL,Integer type) {
  2.     return getHostname(enableSSL,type) + path;
  3. }

 

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片

  1. private static String getHostname(boolean enableSSL,Integer type) {
  2.     if(type == RequestTypeEnum.PUSH.value())
  3.         return enableSSL? HOST_NAME_SSL :HOST_NAME;
  4.     if(type == RequestTypeEnum.RECEIVE.value())
  5.         return enableSSL? RECEIVE_HOST_NAME:RECEIVE_HOST_NAME;
  6.     return null;
  7. }

在这里进行判断,如果enableSSL为false则发送消息请求地址为HOST_NAME,实际上这个enableSSL在BaseClient类中默认为false

 

 

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片

  1. public boolean enableSSL = false;

HOST_NAME就是官方文档中所说的默认请求地址:

 

 

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片

  1. public static String HOST_NAME = “http://api.jpush.cn:8800”;

 

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片

  1. public static  String RECEIVE_HOST_NAME = “https://report.jpush.cn:443”;

标签