Android XMPP Communication Custom Packet&provider_android

Source: Internet
Author: User
Tags abstract closing tag static class xml parser android push notification

Summary

In the XMPP communication process, Asmack provides the packet component is iq,message,presence three kinds: IQ is used for query messages for message passing presence for state interaction they are all packet subclasses, The essence is the XML format used to encapsulate messages into responses for data exchange, which has good scalability.

Brief introduction

We take the Open source project Androidpn as an example:

ANDROIDPN (Android push Notification) is a Java open source Android push Notification implementation based on the XMPP protocol. It contains the full client and server side.

The ANDROIDPN includes the server and client side, and the project name is Androidpn-server and androidpn-client.

In fact, Androidpn-server can support apps running on platforms such as Ios,uwp,windows,linux, not just Android, so you want to change the name of the project to XPN (Xmpp Push Notification) Seems to be more in line with its actual scene, we later involve Android Push notification collectively known as XPN.

XNP Current status

The project has ceased to be updated since January 2014, and the Asmack project has ceased to be updated, and the authors suggest using OpenFire's official smack4.0, but the jar will be particularly large and especially big. Of course, we've downloaded a newer stable version of asmack8.10.0 that can be used exclusively for learning and scaling.

Project related download site

Asmack-github.com-asmack Project Address

Asmack-asmack.freakempire.de-asmack Mirror Address

ANDROIDPN (XPN)-github.com-androidpn download Address

I. About packet Packets

Packet is a iq,message,presence parent class that implements the message component type.

Message semantics messages

A message is a basic push messaging method that does not require a response. It is mainly used in applications such as IM, groupchat, alert and notification.
The main properties are as follows:

Type property, which has 5 main types:
Normal: Similar to email, the main feature is not required response;
Chat: Similar to QQ friends instant chat, the main feature is real-time communication;
Groupchat: Like a group chat in a chat room;
Headline: For sending alert and notification;
Error: If send message error, found the wrong entity will use this category to notify the sender error;

To attribute: Identifies the recipient of the message.

From attribute: Refers to the sender's name or label. To prevent an address from leaking out, this address is usually filled by the sender's server instead of the sender.
Payload (payload): for example Body,subject

<message to= "lily@jabber.org/contact" 
 type= "chat" > 
  <body> Hello, are you busy </body> 
</ Message>

Attend the information semantics presence

Presence is used to indicate the user's status, such as: online, Away, DND (Do Not Disturb). When you change your state, you insert a presence element in the context of the stream to indicate its state. To accept presence messages, you must go through a licensing process called presence subscription.
Property:

Type attribute, not required. There are the following categories
Subscribe: Subscribing to the status of other users
Probe: Request to get the status of another user
Unavailable: Not available, offline (offline) status

To attribute: Identifies the recipient of the message.

From attribute: Refers to the sender's name or label.

Load (payload):
Show
Chat: In Chat
Away: Leave temporarily
Xa:extend Away, long time to leave
DND: Don't Disturb
Status: Free format, readable text. Also known as rich presence or extended presence, it is often used to express the user's current mood, activities, listening songs, watching videos, the chat room, visiting pages, playing games, and so on.
Priority: Range -128~127. High-priority resource can accept messages sent to bare Jid, and low priority resource cannot. Priority is
<presence from= "ALICE@WONDERLAND.LIT/PDA" >
<show>xa</show>
<status>down the Rabbit hole!</status>
</presence>

IQ semantics

A request/response mechanism from which a request is sent from one entity and another entity receives the request and responds. For example, the client inserts an element into the context of the stream, requests a list of friends from the server, and the server returns one, which is the result of the request.
The primary property is type. Including:
Get: Gets the current domain value. Similar to the HTTP GET method.
Set: Sets or replaces the value of a get query. Similar to the HTTP put method.
Result: Indicates a successful response to a previous query. Similar to HTTP status code 200.
Error: Errors that occur in queries and responses.
<iq from= "ALICE@WONDERLAND.LIT/PDA"
Id= "Rr82a1z7"
To= "Alice@wonderland.lit"
Type= "Get" >
<query xmlns= "Jabber:iq:roster"/>
</iq>

Two. Custom packet

Because the server and the client use different packet, but the data format they interact with is XML, so this process we understand the XML implementation process.

1. Define Packet Package objects

Because of the limitations of Asmack label parsing, we cannot customize parsing unless we modify the source code, here for simplicity, only one of the existing tags can be inherited.

I do not follow the project code Notificationiq as an example, here did not inherit packet, but inherited the IQ

Import Org.jivesoftware.smack.packet.IQ;
 /** * This class represents a Notifcatin IQ packet.
  * * @author Sehwan Noh (devnoh@gmail.com) */public class Notificationiq extends IQ {private String ID;
  Private String Apikey;
  Private String title;
  Private String message;
  Private String URI; Public Notificationiq () {} @Override public String getchildelementxml () {StringBuilder buf = new StringBuilder
    (); Buf.append ("<"). Append ("Notification"). Append ("Xmlns=\"). Append ("Androidpn:iq:notification"). Append ("\"
    > ");
    if (ID!= null) {buf.append ("<id>"). Append (ID). Append ("</id>");
    } buf.append ("</"). Append ("Notification"). Append (">");
  return buf.tostring ();
  Public String GetId () {return id;
  public void SetId (String id) {this.id = ID;
  Public String Getapikey () {return apikey;
  } public void Setapikey (String apikey) {this.apikey = Apikey; Public String GetTitle () {
    return title;
  public void Settitle (String title) {this.title = title;
  Public String GetMessage () {return message;
  public void Setmessage (String message) {this.message = message;
  Public String GetURI () {return URI;
  public void Seturi (String url) {this.uri = URL;
 }
}

Where Getchildelementxml () is a subclass of IQ, which is used to splice the direct point under <iq>.

Public abstract class IQ extends Packet {private type type = Type.get;
  Public IQ () {super ();
    Public IQ (IQ IQ) {super (IQ);
  Type = Iq.gettype ();
   }/** * Returns the type of the IQ packet.
   * * @return The type of the IQ packet.
  */Public Type GetType () {return type;
   }/** * Sets the type of the IQ packet.
   * * @param type of the IQ packet.
    */public void SetType (type type) {if (type = = null) {This.type = Type.get;
    else {this.type = type;
    } public String ToXML () {StringBuilder buf = new StringBuilder ();
    Buf.append ("<iq");
    if (Getpacketid ()!= null) {buf.append ("id=\" + getpacketid () + "\");
    } if (Getto ()!= null) {buf.append ("to=\"). Append (Stringutils.escapeforxml ()). Getto ("\");
    } if (Getfrom ()!= null) {buf.append ("from=\"). Append (Stringutils.escapeforxml ()). Getfrom ("\"); } if (type = null) {buf.append ("type=\" get\ ">");
    else {buf.append ("type=\"). Append (GetType ()). Append (">");
    }//Add the query section if there is one.
    String queryxml = Getchildelementxml ();
    if (queryxml!= null) {buf.append (queryxml);
    }//Add the error sub-packet, if there is one.
    Xmpperror error = GetError ();
    if (Error!= null) {Buf.append (Error.toxml ());
    } buf.append ("</iq>");
  return buf.tostring (); }/** * Returns the sub-element XML section of the IQ packet, or <tt>null</tt> if there * isn ' t one. Packet extensions <b>must</b> is included, if any are defined.<p> * * Extensions of this class Mus
   T override this method.
   * @return the child element section of the IQ XML.
  * * Public abstract String getchildelementxml (); /** * Convenience method to create a new empty {@link Type#result IQ. Type.result} * IQ based on a {@link Type#get IQ. Type.get} or {@link type#set IQ. Type.set} * IQ. 
   The new packet would be initialized with:<ul> * <li>the Sender set to the recipient of the originating IQ.
   * <li>the recipient set to the sender of the originating IQ. * <li>the Type set to {@link Type#result IQ.
   Type.result}. * <li>the ID set to the ID of the originating IQ.
   * <li>no child element of the IQ element. * </ul> * @param iq @link Type#get IQ. Type.get} or {@link type#set IQ.
   Type.set} IQ packet. * @throws illegalargumentexception If the IQ packet does not have a type of * {@link Type#get IQ. Type.get} or {@link type#set IQ. Type.set}. * @return A new {@link Type#result IQ.
   Type.result} IQ based on the originating IQ. * public static IQ Createresultiq (final IQ request) {if (!) ( Request.gettype () = = Type.get | | Request.gettype () = = Type.set)) {throw new IllegalArgumentException ("IQ must is of Type ' SET ' or ' get '). OriginaL IQ: "+ request.toxml ());
      Final IQ result = new IQ () {public String getchildelementxml () {return null;
    }
    };
    Result.settype (Type.result);
    Result.setpacketid (Request.getpacketid ());
    Result.setfrom (Request.getto ());
    Result.setto (Request.getfrom ());
  return result; /** * Convenience method to create a new {@link type#error IQ. Type.error} IQ * Based on a {@link Type#get IQ. Type.get} or {@link type#set IQ. Type.set} * IQ. 
   The new packet would be initialized with:<ul> * <li>the Sender set to the recipient of the originating IQ.
   * <li>the recipient set to the sender of the originating IQ. * <li>the Type set to {@link type#error IQ.
   Type.error}. * <li>the ID set to the ID of the originating IQ.
   * <li>the child element contained in the associated originating IQ.
   * <li>the provided {@link xmpperror xmpperror}. * </ul> * @param iq the {@linkType#get IQ. Type.get} or {@link type#set IQ.
   Type.set} IQ packet.
   * @param error The error to associate with the created IQ packet. * @throws illegalargumentexception If the IQ packet does not have a type of * {@link Type#get IQ. Type.get} or {@link type#set IQ. Type.set}. * @return A new {@link type#error IQ.
   Type.error} IQ based on the originating IQ. * * public static IQ Createerrorresponse (final IQ request, final Xmpperror error) {if (!) ( Request.gettype () = = Type.get | | Request.gettype () = = Type.set)) {throw new IllegalArgumentException ("IQ must is of Type ' SET ' or ' get ').
    Original IQ: "+ request.toxml ()); 
      Final IQ result = new IQ () {public String getchildelementxml () {return request.getchildelementxml ();
    }
    };
    Result.settype (Type.error);
    Result.setpacketid (Request.getpacketid ());
    Result.setfrom (Request.getto ());
    Result.setto (Request.getfrom ());
    Result.seterror (Error);
  return result;
}  /** * A class to represent the type of the IQ packet. The types are: * * <ul> * <li>iq. Type.get * <li>iq. Type.set * <li>iq. Type.result * <li>iq.
    Type.error * </ul> * public static class Type {public static final Type get = new Type (' get ');
    public static final Type SET = new Type ("SET");
    The public static final Type result = the new type ("result");
    public static final Type ERROR = new Type ("error"); /** * Converts a String into the corresponding types.
     Valid String values * that can is converted to types are: ' Get ', ' set ', ' result ', and ' error '.
     * * @param type the String value to covert.
     * @return the corresponding Type.
      */public static Type fromstring (String type) {if (Type = = null) {return null;
      } type = Type.tolowercase ();
      if (get.tostring (). Equals (type)) {return get; else if (set.tostring (). Equals (Type)){return SET;
      else if (error.tostring (). Equals (type)) {return ERROR;
      else if (result.tostring (). Equals (type)) {return result;
      else {return null;
    }} private String value;
    Private Type (String value) {this.value = value;
    Public String toString () {return value;
 }
  }
}

You can eventually generate data of the following structure

<iq from= "" >
 <nofitication xlns= "" >
<iq>

Our use of the project is simple

xmppManager.getConnection().sendPacket(<NotificationIQ>niq)

Of course, the above just realized the object->xml, and then we realize xml->data

2. Realize Iqprovider

First look at the Iqprovider source

Public interface Iqprovider {

  /**
   * Parse the IQ sub-document and create an IQ instance. Each IQ must have a
   * single child element. At the beginning of the "method" call, the XML parser * 'll be positioned at the
   opening tag of the "the IQ child element."  t the end
   * is call, the parser <b>must</b> is positioned on the closing tag * of the child
   element.
   *
   * @param parser an XML parser.
   * @return A new IQ instance.
   * @throws Exception If an error occurs parsing the XML.
   * * Public
  IQ Parseiq (Xmlpullparser parser) throws Exception;
}

Implementing a custom parsing tool

public class Notificationiqprovider implements Iqprovider {public Notificationiqprovider () {} @Override Public
    IQ Parseiq (Xmlpullparser parser) throws Exception {Notificationiq notification = new Notificationiq (); For (Boolean = false;!done;)
      {int eventtype = Parser.next ();
        if (EventType = = 2) {if ("id". Equals (Parser.getname ())) {Notification.setid (Parser.nexttext ());
        } if ("Apikey". Equals (Parser.getname ())) {Notification.setapikey (Parser.nexttext ());
        } if ("title". Equals (Parser.getname ()) {Notification.settitle (Parser.nexttext ());
        } if ("Message". Equals (Parser.getname ()) {Notification.setmessage (Parser.nexttext ());
        } if ("uri". Equals (Parser.getname ()) {Notification.seturi (Parser.nexttext ());
 } else if (EventType = 3 && "notification". Equals (Parser.getname ())) {done = true;     } return notification;
 }
}

How to use the project

Providermanager.getinstance (). Addiqprovider ("Notification",
              "Androidpn:iq:notification",
              New Notificationiqprovider ());

The following calls are made in the Packetparserutils class in Asmack

 Object Provider = Providermanager.getinstance (). Getiqprovider (ElementName, namespace);
          if (provider!= null) {
            if (provider instanceof Iqprovider) {
              Iqpacket = ((Iqprovider) provider). PARSEIQ (parser);
            }
            else if (provider instanceof Class) {
              iqpacket = (IQ) packetparserutils.parsewithintrospection (ElementName,
                  (class<?>) provider, parser);
            }
          

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

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.