The smack package used in Android is actually called Asmack, which provides two different ways to connect: Sockets and HttpClient. It also provides many APIs for operating the XMPP protocol and facilitates the expansion of various custom protocols. We do not need to redefine a set of receive mechanisms to extend the new protocol, just inherit and then handle our own protocol in the class. Today, the main point of this article is to say two points, the point is how the message is received, the other is how the message notifies the event.
The general idea
1. Connect to the server using the socket
2. Associate the Xmlpullparser data source to the socket's InputStream
3. The boot thread keeps looping through messages
4. Encapsulate the received message parsing XML processing into a packet package
5. Broadcast the package to all registered event listener classes
Gradually break
(the statement in the following article, it is best to understand the use of smack, so as to achieve a deep understanding)
(Keep in mind: This article explains only the classes and methods that are used, reducing some of the code that is irrelevant to the topic of this article, leaving only one line running from the connection to receiving the message.) )
Parsing this thing is going to start with the initial invocation as the entrance, cobwebs, gradually uncovered.
1.
Packetlistener Packetlistener = new Packetlistener () {
@Override public void Processpacket (Packet Packet) { System.out . println ("Activity----processpacket" + Packet.toxml ()); } ; Packetfilter packetfilter = new Packetfilter () { @Override public Boolean accept (Packet Packet) { System.out.println ("Activity----accept" + packet.toxml ()); return true; } };
Explanation: The creation of the packet monitoring and packet filtering, when there is a message will be broadcast to all registered listening, of course, the premise is to pass packetfilter filtering.
2.
Connection = new Xmppconnection ();
Xmppconnection in this constructor the main configuration IP address and port (super (New Connectionconfiguration ("169.254.141.109", 9991));)
3.
Connection.addpacketlistener (Packetlistener, Packetfilter);
Connection.connect ();
Register the listener to begin the initialization of the connection.
4.
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 ();}
Set up the socket object via the IP and port
6.
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 block e1.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 variablesinitreaderandwriter ();p acketreader = new Packetreader (this); Addpacketlistener (Debugger.getreaderlistener (), null);//Start the packet reader. The startup () method would block until we//get a opening stream packet back from Server.packetReader.startup ();
}
From the three methods can be seen, the establishment of reader and writer object associated to the socket InputStream, instantiate Consoledebugger, the class is mainly to print out the received messages, to reader set up a message listener. The Packetreader object is then created and started. Packetreader primarily responsible for handling and notifying of messages
7.
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 = Connecti On 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'll use a single thread with an unbounded queue. Listenerexecutor = executors. Newsinglethreadexecutor (New Threadfactory () {@Override Public 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 have been established. A connection'll is attempted for a maximum * of five seconds. An xmppexception would 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's being used by the reader to the 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); } }}
}
When you create the class, you initialize the thread and Executorservice, and then call the Resetparser () method to set the input source for the parser (here is the key, the parser data is obtained here), call the startup thread, loop through the parser, If a message is received that differs from the message protocol, it calls the different methods in the Packetparserutils class, where Parsemessage () is called to process the message, parsing the message in the method and returning the packet package. The returned package calls the Processpacket method, notifying all listeners registered for Packetcollector, followed by the message (Listenerexecutor.submit (new listenernotification (packet) ); ) is passed to all monitors registered with the Packetlistener. This will trigger the listener event that was registered before the activity started, thus completing the entire process.
More than 7.
The rest is some auxiliary packages, very simple. For example, the Packetcollector class, which is used primarily to handle requests that need to wait for a reply after it is sent.
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;}
The method is to retrieve the package, first filtering and then put in the queue, and finally through the NextResult to get the package, so that a request to complete a reply.
So the whole process is done, and finally a summary, (just so simple 0):
Project Download (only the client, the server is a simple socket to accept, in order to exercise our ability to write code, the servers that can only write their own 0, in fact, is too lazy to upload, the code is very simple)
Http://files.cnblogs.com/not-code/simualteSmack.zip
This article is original, if need reprint, please indicate author and source, thank you!
Source: http://www.cnblogs.com/not-code/archive/2011/08/01/2124340.html
Android Smack Source Analysis--receive messages and how to parse messages