1.端到端確保發送(類似短信)。
其實這個就是xmpp協議的XEP-0184: Message Delivery Receipts.
裏邊爲了確保消息的到達,需要接收方返回回執,這樣發送方就知道對方是否確切收到消息。
當然咯,接收回執過程中也可能出現斷線,導致發送方收不到回執,而認爲接收方沒收到,再重新發的問題,這個需要接收方過濾掉重複的信息來解決。
其實這個協議,asmack在0.8.3版本就已經支持,具體什麼版本開始,就懶得去研究了。
需要注意的是:這個是兩個客戶端之間的事情,即openfire什麼也不用幹,只要客戶端都支持xep-0184就可以了。
下面簡單說下xep-0184協議的交互內容:
發送方發送一個需要回執的消息:
- <message from='[email protected]/westminster'
- id='richard2-4.1.247'
- to='[email protected]/throne'>
- <body>My lord, dispatch; read o'er these articles.</body>
- <request xmlns='urn:xmpp:receipts'/>
- </message>
接收方收到消息後,返回的消息:
- <message from='[email protected]/throne'
- id='bi29sg183b4v'
- to='[email protected]/westminster'>
- <received xmlns='urn:xmpp:receipts' id='richard2-4.1.247'/>
- </message>
注意回執的id要與接收的packetID對應。
好了,瞭解原理了。大家來看看asmack是怎麼實現的。
http://bamboo.igniterealtime.org/browse/SMACK-TRUNK-59/commit 上說的好簡單,實際上你不會成功的,因爲asmack有bug,目前最新的0.8.5上也沒解決。
下面跟大家介紹怎麼使用消息回執及解決這個bug。
發送需要回執的消息前,調用
- DeliveryReceiptManager.addDeliveryReceiptRequest(packet);
- myConnection.sendPacket(packet);
來爲你的packet添加<request xmlns='urn:xmpp:receipts'/>節點。
在初始化xmppconnection後,調用
- DeliveryReceiptManager.getInstanceFor(myConnection)
- .enableAutoReceipts();
來設置自動進行回執,設置後,回執的事情就不用我們自己操心啦。
好了,要做的事情就這麼點。額,,,本來應該就這麼點。但是。。asmack有bug啊,他把request跟received都用同一個ExtensionProvider啦!!
證據在org.jivesoftware.smackx.ConfigureProviderManager類裏邊這兩句:
- // XEP-184 Message Delivery Receipts
- pm.addExtensionProvider("received", "urn:xmpp:receipts", new DeliveryReceipt.Provider());
- pm.addExtensionProvider("request", "urn:xmpp:receipts", new DeliveryReceipt.Provider());
都用了同一個Provider,當然出問題了。就是接受者無法找到<request xmlns='urn:xmpp:receipts'/>節點,因爲DeliveryReceipt.Provider()生成的是received節點。
於是乎,自動回執沒有效果。
“改吧!。。”
“不改jar包行不行啊?”
“行啊!”
如下:
- sAndroid = SmackAndroid.init(cxtContext);
- ProviderManager pm = ProviderManager.getInstance();
- // add delivery receipts
- pm.addExtensionProvider(DeliveryReceipt.ELEMENT, DeliveryReceipt.NAMESPACE,
- new DeliveryReceipt.Provider());
- pm.addExtensionProvider(DeliveryReceiptRequest.ELEMENT, DeliveryReceipt.NAMESPACE,
- new DeliveryReceiptRequest.Provider());
將jar包中錯誤的設置,重新設置一下。這樣,消息回執功能就大功告成啦。。
xep-0184裏邊還講了如何判斷客戶端是否支持消息回執的問題,如果你有這樣的需求,就自己去了解吧。
2.openfire服務端確保消息發送到達(待續)
我不知是否是由於MINA太舊的原因,導致openfire在nio發送的過程中,無法捕獲發送異常,導致無法識別異常斷線的客戶端,也就不能準確的保存離線消息。
openfire目前用的MINA是1.1.7版本,可能是這個版本有問題。apache在這版本上進行了重大的調整和改造,版本號直接改成2.0.0。因此直接升級openfire的MINA包難度很大,連openfire開發者們都拖了這麼些年不更新MINA版本。。
這個原因純屬個人猜測,於是這個方法走不通。有興趣的同學可以試試,熟悉MINA的人應該能看出來。
既然底層機制不可變,那就只能通過自己的手法來處理了。