極光推送-服務端端智慧人社訊息推送方式

Aurora Polaris發表於2016-11-30

極光推送-服務端端智慧人社訊息推送方式


文章轉自:http://blog.csdn.NET/u014733374/article/details/43560983

最近一直在做後臺開發,但心裡還是總惦記著Android,感覺還是Android有意思。正好專案中要用到極光推送,今天抽空來記錄下這兩天的研究成果。

         我們知道iOS有自己的推送服務,但很遺憾Android沒有原生的推送服務,現在有很多第三方的推送服務,比如個推、極光、亞馬遜、百度雲、聚能等。今天我們就來研究下極光推送的後臺伺服器如何實現。

         關鍵點:

        1.首先最好是把極光官網Java後臺伺服器的demo下載下來,裡面有我們需要的jar包,以及example.

        2.極光推送的關鍵jpushClient = new JPushClient(masterSecret, appKey, 3);就是這個類。其中的引數需要我們從極光官網註冊開發者,然後建立具體專案獲取相應的兩                 個key值。其中appKey值就是我們手機端對應的key值

        3.極光推送給我們提供了很多種推送的方式,我們可以選擇某一個平臺進行推送(Android ,IOS ,Windows Phone),也可以全部推送;我們可以針對某個特別的使用者進行推送(設定alisa),也可以針對特別的群體進行推送(設定tag),第三個引數是設定推送保留的時間,只要在有效時間內上線就可以收到推送資訊

        4. 極光推送現在都用https連線,提交請求是post,獲取資料為get


        ok 接下來就看服務端的實現(JAVA),JdPush推送方法+一個Servlet

  1. package com.weiwend.jdpush;  
  2.   
  3. import org.slf4j.Logger;  
  4. import org.slf4j.LoggerFactory;  
  5.   
  6. import cn.jpush.api.JPushClient;  
  7. import cn.jpush.api.common.resp.APIConnectionException;  
  8. import cn.jpush.api.common.resp.APIRequestException;  
  9. import cn.jpush.api.push.PushResult;  
  10. import cn.jpush.api.push.model.Message;  
  11. import cn.jpush.api.push.model.Options;  
  12. import cn.jpush.api.push.model.Platform;  
  13. import cn.jpush.api.push.model.PushPayload;  
  14. import cn.jpush.api.push.model.audience.Audience;  
  15. import cn.jpush.api.push.model.audience.AudienceTarget;  
  16. import cn.jpush.api.push.model.notification.AndroidNotification;  
  17. import cn.jpush.api.push.model.notification.IosNotification;  
  18. import cn.jpush.api.push.model.notification.Notification;  
  19.   
  20. public class Jdpush {  
  21.      protected static final Logger LOG = LoggerFactory.getLogger(Jdpush.class);  
  22.   
  23.      // demo App defined in resources/jpush-api.conf   
  24.   
  25.     public static final String TITLE = "申通快遞";  
  26.     public static final String ALERT = "祝大家新春快樂";  
  27.     public static final String MSG_CONTENT = "申通快遞祝新老客戶新春快樂";  
  28.     public static final String REGISTRATION_ID = "0900e8d85ef";  
  29.     public static final String TAG = "tag_api";  
  30.       
  31.     public  static JPushClient jpushClient=null;  
  32.       
  33.     public static void testSendPush(String appKey ,String masterSecret) {  
  34.           
  35.           
  36.           
  37.          jpushClient = new JPushClient(masterSecret, appKey, 3);  
  38.           
  39.         // HttpProxy proxy = new HttpProxy("localhost", 3128);  
  40.         // Can use this https proxy: https://github.com/Exa-Networks/exaproxy  
  41.          
  42.           
  43.         // For push, all you need do is to build PushPayload object.  
  44.         //PushPayload payload = buildPushObject_all_all_alert();  
  45.          //生成推送的內容,這裡我們先測試全部推送  
  46.         PushPayload payload=buildPushObject_all_alias_alert();  
  47.           
  48.           
  49.         try {  
  50.             System.out.println(payload.toString());  
  51.             PushResult result = jpushClient.sendPush(payload);  
  52.             System.out.println(result+"................................");  
  53.               
  54.             LOG.info("Got result - " + result);  
  55.               
  56.         } catch (APIConnectionException e) {  
  57.             LOG.error("Connection error. Should retry later. ", e);  
  58.               
  59.         } catch (APIRequestException e) {  
  60.             LOG.error("Error response from JPush server. Should review and fix it. ", e);  
  61.             LOG.info("HTTP Status: " + e.getStatus());  
  62.             LOG.info("Error Code: " + e.getErrorCode());  
  63.             LOG.info("Error Message: " + e.getErrorMessage());  
  64.             LOG.info("Msg ID: " + e.getMsgId());  
  65.         }  
  66.     }  
  67.       
  68.     public static PushPayload buildPushObject_all_all_alert() {  
  69.         return PushPayload.alertAll(ALERT);  
  70.     }  
  71.       
  72.     public static PushPayload buildPushObject_all_alias_alert() {  
  73.         return PushPayload.newBuilder()  
  74.                 .setPlatform(Platform.all())//設定接受的平臺  
  75.                 .setAudience(Audience.all())//Audience設定為all,說明採用廣播方式推送,所有使用者都可以接收到  
  76.                 .setNotification(Notification.alert(ALERT))  
  77.                 .build();  
  78.     }  
  79.       
  80.     public static PushPayload buildPushObject_android_tag_alertWithTitle() {  
  81.         return PushPayload.newBuilder()  
  82.                 .setPlatform(Platform.android())  
  83.                 .setAudience(Audience.all())  
  84.                 .setNotification(Notification.android(ALERT, TITLE, null))  
  85.                 .build();  
  86.     }  
  87.       
  88.     public static PushPayload buildPushObject_android_and_ios() {  
  89.         return PushPayload.newBuilder()  
  90.                 .setPlatform(Platform.android_ios())  
  91.                 .setAudience(Audience.tag("tag1"))  
  92.                 .setNotification(Notification.newBuilder()  
  93.                         .setAlert("alert content")  
  94.                         .addPlatformNotification(AndroidNotification.newBuilder()  
  95.                                 .setTitle("Android Title").build())  
  96.                         .addPlatformNotification(IosNotification.newBuilder()  
  97.                                 .incrBadge(1)  
  98.                                 .addExtra("extra_key""extra_value").build())  
  99.                         .build())  
  100.                 .build();  
  101.     }  
  102.       
  103.     public static PushPayload buildPushObject_ios_tagAnd_alertWithExtrasAndMessage() {  
  104.         return PushPayload.newBuilder()  
  105.                 .setPlatform(Platform.ios())  
  106.                 .setAudience(Audience.tag_and("tag1""tag_all"))  
  107.                 .setNotification(Notification.newBuilder()  
  108.                         .addPlatformNotification(IosNotification.newBuilder()  
  109.                                 .setAlert(ALERT)  
  110.                                 .setBadge(5)  
  111.                                 .setSound("happy")  
  112.                                 .addExtra("from""JPush")  
  113.                                 .build())  
  114.                         .build())  
  115.                  .setMessage(Message.content(MSG_CONTENT))  
  116.                  .setOptions(Options.newBuilder()  
  117.                          .setApnsProduction(true)  
  118.                          .build())  
  119.                  .build();  
  120.     }  
  121.       
  122.     public static PushPayload buildPushObject_ios_audienceMore_messageWithExtras() {  
  123.         return PushPayload.newBuilder()  
  124.                 .setPlatform(Platform.android_ios())  
  125.                 .setAudience(Audience.newBuilder()  
  126.                         .addAudienceTarget(AudienceTarget.tag("tag1""tag2"))  
  127.                         .addAudienceTarget(AudienceTarget.alias("alias1""alias2"))  
  128.                         .build())  
  129.                 .setMessage(Message.newBuilder()  
  130.                         .setMsgContent(MSG_CONTENT)  
  131.                         .addExtra("from""JPush")  
  132.                         .build())  
  133.                 .build();  
  134.     }  
  135. }  


可以看到上面我們推送平臺設定的是所有平臺,Audience設定為all(所有使用者),這裡key值和masterSecret值放在servlet中了。


servlet很簡單,只要傳入兩個key值,呼叫該方法就可以

  1. package com.weiwend.jdpush.servlet;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import javax.servlet.ServletException;  
  6. import javax.servlet.http.HttpServlet;  
  7. import javax.servlet.http.HttpServletRequest;  
  8. import javax.servlet.http.HttpServletResponse;  
  9.   
  10. import com.sun.org.apache.xml.internal.serializer.utils.Utils;  
  11. import com.weiwend.jdpush.Jdpush;  
  12. import com.weiwend.jdpush.utils.Base64Utils;  
  13.   
  14. /** 
  15.  * Servlet implementation class tuisong 
  16.  */  
  17. public class tuisong extends HttpServlet {  
  18.     private static final long serialVersionUID = 1L;  
  19.          
  20.     private static final String appKey ="84cf5ee2099c654aa03a5d70";  
  21.     private static final String masterSecret = "7cf23f25a41806d5fd29e3c5";  
  22.       
  23.     public tuisong() {  
  24.         super();  
  25.         // TODO Auto-generated constructor stub  
  26.     }  
  27.   
  28.     /** 
  29.      * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) 
  30.      */  
  31.     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
  32.         Jdpush.testSendPush(appKey,masterSecret);  
  33.         System.out.println("sucess");  
  34.     }  
  35.   
  36.     /** 
  37.      * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) 
  38.      */  
  39.     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
  40.         // TODO Auto-generated method stub  
  41.     }  
  42.   
  43. }  


最後來看下執行的結果,可以看到,提交資料是以json格式。如果返回{"msg_id":1663001319,"sendno":1981162191}這樣資料說明推送已經成功傳送


  1. {"platform":"all","audience":"all","notification":{"alert":"祝大家新春快樂"},"options":{"sendno":1981162191,"apns_production":false}}  
  2. {"msg_id":1663001319,"sendno":1981162191}................................  
  3. sucess  


原始碼分析:

 JPushClient jpushClient = new JPushClient(masterSecret, appKey, 3);實際上是例項化了一下三個類

  1. public JPushClient(String masterSecret, String appKey, int maxRetryTimes) {  
  2.         _pushClient = new PushClient(masterSecret, appKey, maxRetryTimes);  
  3.         _reportClient = new ReportClient(masterSecret, appKey, maxRetryTimes);  
  4.         _deviceClient = new DeviceClient(masterSecret, appKey, maxRetryTimes);  
  5.     }  

PushPayload payload = buildPushObject_all_all_alert();,PushPayload類裡包含了傳遞和返回的所有資料

  1. public class PushPayload implements PushModel {  
  2.     private static final String PLATFORM = "platform";  
  3.     private static final String AUDIENCE = "audience";  
  4.     private static final String NOTIFICATION = "notification";  
  5.     private static final String MESSAGE = "message";  
  6.     private static final String OPTIONS = "options";  
  7.       
  8.     private static final int MAX_GLOBAL_ENTITY_LENGTH = 1200;  // Definition acording to JPush Docs  
  9.     private static final int MAX_IOS_PAYLOAD_LENGTH = 220;  // Definition acording to JPush Docs  
  10.       
  11.     private static Gson _gson = new Gson();  
  12.       
  13.     private final Platform platform;  
  14.     private final Audience audience;  
  15.     private final Notification notification;  
  16.     private final Message message;  
  17.     private Options options;  
  18.       
  19.       
  20.     private PushPayload(Platform platform, Audience audience,   
  21.             Notification notification, Message message, Options options) {  
  22.         this.platform = platform;  
  23.         this.audience = audience;  
  24.         this.notification = notification;  
  25.         this.message = message;  
  26.         this.options = options;  
  27.     }  


 PushResult result = jpushClient.sendPush(payload);可以看到就是sendPost方法,然後接受返回的資料

  1. public PushResult sendPush(PushPayload pushPayload) throws APIConnectionException, APIRequestException {  
  2.        Preconditions.checkArgument(! (null == pushPayload), "pushPayload should not be null");  
  3.          
  4.        if (_globalSettingEnabled) {  
  5.            pushPayload.resetOptionsTimeToLive(_timeToLive);  
  6.            pushPayload.resetOptionsApnsProduction(_apnsProduction);  
  7.        }  
  8.          
  9.        ResponseWrapper response = _httpClient.sendPost(_baseUrl + PUSH_PATH, pushPayload.toString());  
  10.          
  11.        return BaseResult.fromResponse(response, PushResult.class);  
  12.    }  


另外我專門找了下sendNo如何生成的,其實就是隨機生成的一個數字

  1. public static Options sendno() {  
  2.        return newBuilder().setSendno(ServiceHelper.generateSendno()).build();  
  3.    }  


 

  1. public static int generateSendno() {  
  2.        return RANDOM.nextInt((MAX - MIN) + 1) + MIN;  
  3.    }  


大家有興趣也可以詳細看一下程式碼的實現.


 

         剛開始值直接下載的demo執行,一直提示Audience沒有對應的使用者,是引文Audience設定了別名alias,而使用者裡面並沒有設定對應的alias,所以找不到對應的使用者。
最後我們來看一張圖,再深入理解下極光推送的原理




 

 


相關文章