Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> AndroidPn源碼分析(二)

AndroidPn源碼分析(二)

編輯:關於Android編程

(一)客戶端與服務器建立連接   上一篇寫到ClientSession createClientSession這裡,創建一個客戶端的session。在SessionManager類中創建了session之後,這裡拼接了兩個xml內容的text。一個是Build the start packet response,創建一個頭條包,作為回應。另外一個是:XMPP 1.0 needs stream features,是xmpp1.0所需要的文件結構。兩個消息的格式內容如下:   <?xml version='1.0' encoding='UTF-8'?><stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" from="127.0.0.1"  id="bdef9c6a" xml:lang="en" version="1.0"> <stream:features> <starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"></starttls> <auth xmlns="http://jabber.org/features/iq-auth"/> <register xmlns="http://jabber.org/features/iq-register"/> </stream:features> 然後,調用connection的deliverRawText方法,將這兩個xml內容通過IOSession的writer方法,傳輸到mina裡面。具體mina怎麼處理,本人還沒有研究過。   到此,根據記錄的log日志,此消息已經發布了。客戶端與服務器建立連接的過程,這裡已經完成。這裡只是一部分,關於客戶端消息的發送,這部分內容也應該不少。   (二)服務器推送消息   從服務器推送消息的時候,會調用NotificationManager類裡面的方法,分別為廣播和對單個用戶發送。這裡主要看廣播。   首先是構造IQ消息體,createNotificationIQ方法來構造。   復制代碼     /**      * Creates a new notification IQ and returns it.      * 構造消息體格式      */     private IQ createNotificationIQ(String apiKey, String title,             String message, String uri) {         Random random = new Random();         String id = Integer.toHexString(random.nextInt());         // String id = String.valueOf(System.currentTimeMillis());           Element notification = DocumentHelper.createElement(QName.get(                 "notification", NOTIFICATION_NAMESPACE));         notification.addElement("id").setText(id);         notification.addElement("apiKey").setText(apiKey);         notification.addElement("title").setText(title);         notification.addElement("message").setText(message);         notification.addElement("uri").setText(uri);           IQ iq = new IQ();         iq.setType(IQ.Type.set);         iq.setChildElement(notification);           return iq;     } 復制代碼 構造後的xml:   復制代碼 <iq type="set" id="860-0" to="[email protected]/AndroidpnClient">     <notification xmlns="androidpn:iq:notification">         <id>11218d6c</id>         <apiKey>1234567890</apiKey>         <title>你好</title>         <message>你好啊</message>         <uri></uri>     </notification> </iq>             復制代碼 在ClientSession中查找指定用戶名的session,如果存在,則發送此條IQ消息。調用connectin的deliver方法,通過ioSession.write(buffer),將xml信息傳輸給mina,並且將發送記錄加1。   客戶端源碼分析:   客戶端代碼很簡單的,依靠xmppmanager維持連接。這裡說一下大概流程。   當客戶端推送消息過來的時候,NotificationReceiver類的onReceive方法接收到消息,在這裡,這時候,已經獲得了所有發過來的數據。在這裡,已經可以做自己的事情了,因為已經有了需要的數據。不過貌似挺多人喜歡在notifier的notify方法中來進行處理。   其他就是自己的業務了。   還有一個是關於客戶端的用戶名和密碼,這個默認是自動生成,也可以自動指定。在XMPPManager的run方法裡面可以修改。修改後會出現一些問題,就是服務器端注冊的時候,會出現用戶名已經存在,重復插入的問題。這個需要在服務器端插入數據的時候修改一下代碼,在UserServiceImpl中修改,為了業務需要,本人把hibernate修改為了mybatis,所以方法略有不同:   復制代碼     public User saveUser(User user) throws UserExistsException {         try {             //修改為自己的用戶登錄             try {                 user=getUserByUsername(user.getUsername());                              } catch (UserNotFoundException e) {                 // TODO Auto-generated catch block                 log.info(user.getUsername()+" is not exist in db ....");                 userDao.saveUser(user);                 e.printStackTrace();             }          } catch (DataIntegrityViolationException e) {             e.printStackTrace();             log.warn(e.getMessage());             throw new UserExistsException("User '" + user.getUsername()                     + "' already exists!");         } catch (EntityExistsException e) { // needed for JPA             e.printStackTrace();             log.warn(e.getMessage());             throw new UserExistsException("User '" + user.getUsername()                     + "' already exists!");         }          return user;     } 復制代碼 這樣就可以了。   關於短線重連,網上也有很多解決方法,是客戶端加一行代碼:   復制代碼  private void addTask(Runnable runnable) {           Log.d(LOGTAG, "addTask(runnable)...");           taskTracker.increase();           synchronized (taskList) {               if (taskList.isEmpty() && !running) {                   running = true;                  futureTask = taskSubmitter.submit(runnable);                  if (futureTask == null) {                      taskTracker.decrease();                   }               } else {               //解決服務器端重啟後,客戶端不能成功連接androidpn服務器               runTask();                   taskList.add(runnable);               }           }           Log.d(LOGTAG, "addTask(runnable)... done");      }  復制代碼 當然,其他還有許多細節,先到這裡,感謝網上那麼多博主寫的一些資料。
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved