AndroidPn源碼分析(二)

來源:互聯網
上載者:User

標籤:android   style   blog   http   color   os   io   strong   

接上篇:

(一)用戶端與伺服器建立串連

上一篇寫到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");     } 

當然,其他還有許多細節,先到這裡,感謝網上那麼多博主寫的一些資料。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.