日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

android smack源码分析——接收消息以及如何解析消息

發(fā)布時(shí)間:2025/3/21 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android smack源码分析——接收消息以及如何解析消息 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>

在android里面用的smack包其實(shí)叫做asmack,該包提供了兩種不同的連接方式:socket和httpclient。該并且提供了很多操作xmpp協(xié)議的API,也方便各種不同自定義協(xié)議的擴(kuò)展。我們不需要自己重新去定義一套接收機(jī)制來擴(kuò)展新的協(xié)議,只需繼承然后在類里處理自己的協(xié)議就可以了。而本文今天主要說兩點(diǎn),一點(diǎn)就是消息是如何接收的,另一點(diǎn)就是消息是如何通知事件的。

總的思路

1.使用socket連接服務(wù)器

2.將XmlPullParser的數(shù)據(jù)源關(guān)聯(lián)到socket的InputStream

3.啟動(dòng)線程不斷循環(huán)處理消息

4.將接收到的消息解析xml處理封裝好成一個(gè)Packet包

5.將包廣播給所有注冊事件監(jiān)聽的類

逐步擊破

(聲明在看下面的文章時(shí),最好先理解一下smack的使用,這樣才能達(dá)到深入的理解)

(謹(jǐn)記:上圖只顯示本文章解釋所要用到的類和方法,減縮了一些跟本文主題無關(guān)的代碼,只留一條貫穿著從建立連接到接收消息的線。)

解析這塊東西打算從最初的調(diào)用開始作為入口,抽絲剝繭,逐步揭開。

  • PacketListener packetListener = new PacketListener() { @Override public void processPacket(Packet packet) { System.out .println("Activity----processPacket" + packet.toXML()); } };

    PacketFilter packetFilter = new PacketFilter() {@Overridepublic boolean accept(Packet packet) {System.out.println("Activity----accept" + packet.toXML());return true;}};

    解釋:創(chuàng)建包的監(jiān)聽以及包的過濾,當(dāng)有消息到時(shí)就會廣播到所有注冊的監(jiān)聽,當(dāng)然前提是要通過packetFilter的過濾。

  • connection = new XMPPConnection();

    XMPPConnection在這構(gòu)造函數(shù)里面主要配置ip地址和端口(super(new ConnectionConfiguration("169.254.141.109", 9991));)

  • connection.addPacketListener(packetListener, packetFilter); connection.connect();

    注冊監(jiān)聽,開始初始化連接。

  • public void connect() { // Stablishes the connection, readers and writers connectUsingConfiguration(config); } 5.

    private void connectUsingConfiguration(ConnectionConfiguration config) { String host = config.getHost(); int port = config.getPort(); try { this.socket = new Socket(host, port); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } initConnection(); } 通過之前設(shè)置的ip和端口,建立socket對象

  • protected void initDebugger() { Class<?> debuggerClass = null; try { debuggerClass = Class.forName("com.simualteSmack.ConsoleDebugger");

    Constructor<?> constructor = debuggerClass.getConstructor(Connection.class, Writer.class, Reader.class);debugger = (SmackDebugger) constructor.newInstance(this, writer,reader);reader = debugger.getReader();} catch (ClassNotFoundException e1) {// TODO Auto-generated catch blocke1.printStackTrace();} catch (Exception e) {throw new IllegalArgumentException("Can't initialize the configured debugger!", e);} }

    private void initReaderAndWriter() { try { reader = new BufferedReader(new InputStreamReader(socket .getInputStream(), "UTF-8")); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } initDebugger(); } private void initConnection() { // Set the reader and writer instance variables initReaderAndWriter();

    packetReader = new PacketReader(this);addPacketListener(debugger.getReaderListener(), null); // Start the packet reader. The startup() method will block until we // get an opening stream packet back from server. packetReader.startup();

    } 從三個(gè)方法可以看出,建立reader和writer的對象關(guān)聯(lián)到socket的InputStream,實(shí)例化ConsoleDebugger,該類主要是打印出接收到的消息,給reader設(shè)置了一個(gè)消息的監(jiān)聽。接著建立PacketReader對象,并啟動(dòng)。PacketReader主要負(fù)責(zé)消息的處理和通知

  • public class PacketReader { private ExecutorService listenerExecutor; private boolean done; private XMPPConnection connection; private XmlPullParser parser; private Thread readerThread;

    protected PacketReader(final XMPPConnection connection) {this.connection = connection;this.init(); }/*** Initializes the reader in order to be used. The reader is initialized* during the first connection and when reconnecting due to an abruptly* disconnection.*/ protected void init() {done = false;readerThread = new Thread() {public void run() {parsePackets(this);}};readerThread.setName("Smack Packet Reader ");readerThread.setDaemon(true);// create an executor to deliver incoming packets to listeners.// we will use a single thread with an unbounded queue.listenerExecutor = Executors.newSingleThreadExecutor(new ThreadFactory() {@Overridepublic Thread newThread(Runnable r) {Thread thread = new Thread(r,"smack listener processor");thread.setDaemon(true);return thread;}});resetParser(); }/*** Starts the packet reader thread and returns once a connection to the* server has been established. A connection will be attempted for a maximum* of five seconds. An XMPPException will be thrown if the connection fails.* */ public void startup() {readerThread.start(); }/*** Shuts the packet reader down.*/ public void shutdown() {done = true;// Shut down the listener executor.listenerExecutor.shutdown(); }private void resetParser() {try {parser = XmlPullParserFactory.newInstance().newPullParser();parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);parser.setInput(connection.reader);} catch (XmlPullParserException xppe) {xppe.printStackTrace();} }/*** Parse top-level packets in order to process them further.* * @param thread* the thread that is being used by the reader to parse incoming* packets.*/ private void parsePackets(Thread thread) {try {int eventType = parser.getEventType();do {if (eventType == XmlPullParser.START_TAG) {if (parser.getName().equals("message")) {processPacket(PacketParserUtils.parseMessage(parser));}System.out.println("START_TAG");} else if (eventType == XmlPullParser.END_TAG) {System.out.println("END_TAG");}eventType = parser.next();} while (!done && eventType != XmlPullParser.END_DOCUMENT&& thread == readerThread);} catch (Exception e) {e.printStackTrace();if (!done) {}} }private void processPacket(Packet packet) {if (packet == null) {return;}// Loop through all collectors and notify the appropriate ones.for (PacketCollector collector : connection.getPacketCollectors()) {collector.processPacket(packet);}// Deliver the incoming packet to listeners.listenerExecutor.submit(new ListenerNotification(packet)); }/*** A runnable to notify all listeners of a packet.*/ private class ListenerNotification implements Runnable {private Packet packet;public ListenerNotification(Packet packet) {this.packet = packet;}public void run() {for (ListenerWrapper listenerWrapper : connection.recvListeners.values()) {listenerWrapper.notifyListener(packet);}} }

    } 創(chuàng)建該類時(shí)就初始化線程和ExecutorService ,接著調(diào)用resetParser() 方法為parser設(shè)置輸入源(這里是重點(diǎn),parser的數(shù)據(jù)都是通過這里獲取),調(diào)用startup啟動(dòng)線程,循環(huán)監(jiān)聽parser,如果接收到消息根據(jù)消息協(xié)議的不同將調(diào)用PacketParserUtils類里的不同方法,這里調(diào)用parseMessage()該方法主要處理message的消息,在該方法里分析message消息并返回packet包。返回的包將調(diào)用processPacket方法,先通知所有注冊了PacketCollector的監(jiān)聽,接著消息(listenerExecutor.submit(new ListenerNotification(packet)); )傳遞給所有注冊了PacketListener的監(jiān)聽。這樣在activity開始之前注冊的那個(gè)監(jiān)聽事件就會觸發(fā),從而完成了整個(gè)流程。

    7以上.

    剩下的就是一些輔助包,很簡單。比如PacketCollector 這個(gè)類,它的用處主要用來處理一些需要在發(fā)送后需要等待一個(gè)答復(fù)這樣的請求。

    protected synchronized void processPacket(Packet packet) { System.out.println("PacketCollector---processPacket"); if (packet == null) { return; } if (packetFilter == null || packetFilter.accept(packet)) { while (!resultQueue.offer(packet)) { resultQueue.poll(); } } } public Packet nextResult(long timeout) { long endTime = System.currentTimeMillis() + timeout; System.out.println("nextResult"); do { try { return resultQueue.poll(timeout, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { /* ignore */ } } while (System.currentTimeMillis() < endTime); return null; } 該方法就是將獲取到的包,先過濾然后放到隊(duì)列里,最后通過nextResult來獲取包,這樣就完成一個(gè)請求收一個(gè)答復(fù)。

    這樣整個(gè)流程就完成了,最后總結(jié)一下,如圖(就這么簡單^0^):

    項(xiàng)目下載(只有客戶端的,服務(wù)端的就是一個(gè)簡單的socket接受,為了鍛煉一下大家的編寫代碼的能力,服務(wù)器那個(gè)只能自己寫咯^0^,其實(shí)是懶得上傳了,代碼很簡單的)

    http://files.cnblogs.com/not-code/simualteSmack.zip

    本文為原創(chuàng),如需轉(zhuǎn)載,請注明作者和出處,謝謝!

    出處:http://www.cnblogs.com/not-code/archive/2011/08/01/2124340.html

    轉(zhuǎn)載于:https://my.oschina.net/yuanxulong/blog/350067

    總結(jié)

    以上是生活随笔為你收集整理的android smack源码分析——接收消息以及如何解析消息的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 2019中文字幕在线 | www天堂网 | 大学生一级片 | 91免费视频免费版 | 农民工hdxxxx性中国 | 国产黄色自拍 | 国产伦精品一区二区三区视频我 | 中文字幕av在线免费观看 | 亚洲免费婷婷 | 精品人妻一区二区三区四区在线 | 日本视频在线免费 | 中文字幕线人 | 久久亚洲综合色 | 极品少妇一区二区 | 国产一区二区三区在线视频 | 成人免费a级片 | 久久艹国产| 天天射寡妇射 | 免费看黄在线 | 色黄网站 | 天天网综合 | 日韩欧美三级在线 | 国产精品免费av | 亚洲精品乱码久久久久久久久久久久 | 午夜剧场免费在线观看 | 欧美女人交配视频 | xx69欧美 | 欧美日韩一区二区在线观看视频 | 欧美日韩黄色 | 69视频免费在线观看 | 成人丁香婷婷 | 日本午夜免费福利视频 | 六月丁香在线视频 | 精品一区二区免费看 | 我的公把我弄高潮了视频 | 日韩福利片在线观看 | 久久夜色精品国产噜噜亚洲av | 亚洲日日日 | 精品产国自在拍 | 国产日韩欧美自拍 | 午夜精品一区二区在线观看 | 国产激情精品 | 亚洲私人网站 | 欧美片一区二区三区 | 爱爱精品 | 国产视频第二页 | 少女与动物高清版在线观看 | 成人国产精品久久久网站 | 亚洲精品免费看 | 亚洲性网 | 好色视频tv| 美女爱爱爱 | 中国白嫩丰满人妻videos | 你懂的在线免费观看 | 色一情| 高清国产午夜精品久久久久久 | av网站免费在线看 | 极品美女高潮出白浆 | 国产精品爽爽爽 | 国产精品最新 | 伊人国产精品 | 99国产精品一区二区三区 | 最近的中文字幕 | 国产精品刘玥久久一区 | 女同亚洲精品一区二区三 | 亚洲精品一区二区三区新线路 | 亚欧中文字幕 | 欧美黄页 | a∨鲁丝一区鲁丝二区鲁丝三区 | 97看片网| 在线一级| 国产成人啪精品午夜在线观看 | 亚洲av综合av一区二区三区 | 亚洲天堂免费观看 | 在线不卡av电影 | 日韩欧洲亚洲AV无码精品 | 国产最新在线 | 天天摸天天操天天干 | 国产精品精品国产色婷婷 | 亚洲综合第一 | 国产精品伦一区二区三区 | 欧美高清视频一区 | 台湾佬美性中文 | 在线观看免费高清在线观看 | 2018中文字幕在线观看 | 青青草视频在线看 | 日韩免费小视频 | 中文字幕乱码中文乱码b站 国产一区二区三区在线观看视频 | 特级淫片aaaaaaa级 | 欧美撒尿777hd撒尿 | 黑人精品无码一区二区三区 | 久久毛片基地 | 性囗交免费视频观看 | 91老师片黄在线观看 | 亚洲一区二区精品 | 理论片午午伦夜理片影院99 | 日韩精品一区不卡 | 九九精品影院 | 桃谷绘里香在线播放 |