Home/Instant Messaging in Android using XMPP(Openfire)

Instant Messaging in Android using XMPP(Openfire)

Published On: 23 January 2017.By .
  • Mobile
  • Product & platform Engineering

Extensible Messaging and Presence Protocol (XMPP) is a communications protocol for message-oriented middleware based on XML (Extensible Markup Language).[1] It enables the near-real-time exchange of structured yet extensible data between any two or more network entities.

In this blog, we are taken Openfire server. Read more about Openfire here  http://www.igniterealtime.org/. We divided in following part.

  • Download Openfire
  • Install Openfire
  • Create a new Project and add dependency in build.gradle
  • Create Chat Manager class
  • Setup with Smack service

 

Download Openfire- Download Openfire from here http://www.igniterealtime.org/downloads/

Install Openfire- You need to follow few step for setup –http://mindbowser.com/openfire-installation-and-database-configuration/

Add dependency in build.gradle- Add the following dependency in build.gradle

compile 'org.igniterealtime.smack:smack-android-extensions:4.1.5'
compile 'org.igniterealtime.smack:smack-tcp:4.1.5'

Build Chat Manager- 

Create Connection-

    XMPPTCPConnectionConfiguration.Builder config = XMPPTCPConnectionConfiguration.builder();
    config.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled);
    config.setServiceName(MyCommunityChatService.XMPP_SERVICE_NAME);
    config.setResource(MyCommunityChatService.XMPP_SERVICE_NAME);
   // Add host address here 
    config.setHost(serverAddress);
    config.setPort(5222);
    config.setDebuggerEnabled(true);

    XMPPTCPConnection.setUseStreamManagementResumptiodDefault(true);
    XMPPTCPConnection.setUseStreamManagementDefault(true);
    mConnection = new XMPPTCPConnection(config.build());

Add Connection Listener –

 XMPPConnectionListener connectionListener = new XMPPConnectionListener();
 mConnection.addConnectionListener(connectionListener);

XmppConnection definition is –

 public class XMPPConnectionListener implements ConnectionListener {
    @Override public void connected(final XMPPConnection mConnection) {

      Log.d("xmpp", "Connected!");
      connected = true;
      if (!mConnection.isAuthenticated()) {
        login();
      }
    }

    @Override public void connectionClosed() {

      Log.d("xmpp", "ConnectionCLosed!");
      connected = false;
      chat_created = false;
      loggedin = false;
    }

    @Override public void connectionClosedOnError(Exception arg0) {

      Log.d("xmpp", "ConnectionClosedOn Error!");
      connected = false;
      chat_created = false;
      loggedin = false;
    }

    @Override public void reconnectingIn(int arg0) {

      Log.d("xmpp", "Reconnectingin " + arg0);
      loggedin = false;
      disconnect();
      initialiseConnection();
    }

    @Override public void reconnectionFailed(Exception arg0) {

      Log.d("xmpp", "ReconnectionFailed!");
      connected = false;
      chat_created = false;
      loggedin = false;
    }

    @Override public void reconnectionSuccessful() {
      Log.d("xmpp", "ReconnectionSuccessful");
      connected = true;
      chat_created = false;
      loggedin = false;
    }

    @Override public void authenticated(XMPPConnection arg0, boolean arg1) {
      Log.d("xmpp", "Authenticated!");
      loggedin = true;

      //      ChatManager.getInstanceFor(mConnection).addChatListener(mChatManagerListener);

      chat_created = false;
      new Thread(new Runnable() {

        @Override public void run() {
          try {
            Thread.sleep(500);
          } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
        }
      }).start();
    }
  }

Setup Packet Reply Timeout- 

 // set packet reply timeout time
   mConnection.setPacketReplyTimeout(10000);

Add Reconnect Manager with Connection

    // Add reconnect manager
    ReconnectionManager.getInstanceFor(mConnection).enableAutomaticReconnection();
    ServerPingWithAlarmManager.onCreate(context);
    ServerPingWithAlarmManager.getInstanceFor(mConnection).setEnabled(true);
    ReconnectionManager.setEnabledPerDefault(true);

Add Ping Manager– Ping manager is ping to a server in fixed interval. If server replies as pong then the client is can communicate with a server. Other call callback onPingFalied method call

    // Add ping manager here
    PingManager.getInstanceFor(mConnection).registerPingFailedListener(new PingFailedListener() {
      @Override public void pingFailed() {
        disconnect();
        initialiseConnection();
      }
    });

Add Stanza(Packet) listener with Connection- 

 mConnection.addAsyncStanzaListener(new StanzaListener() {
      private ChatMessage superMessage;
      private DelayInformation delayInformation;

      @Override public void processPacket(Stanza packet)
          throws SmackException.NotConnectedException {
        if (!packet.getFrom().contains(mConnection.getUser())) {
          Log.i("TAG", "processPacket: new packet received in service");
          superMessage = ChatMessage.instanceOf(((Message) packet).getBody());

          delayInformation = null;
          try {
            delayInformation = packet.getExtension("delay", "urn:xmpp:delay");
          } catch (Exception e) {
            e.printStackTrace();
          }
          if (delayInformation != null) {
            Date date = delayInformation.getStamp();
            // set up message delay information here
          }
          // Message receive here

        }
      }
    }, new StanzaFilter() {
      @Override public boolean accept(Stanza stanza) {
        if (stanza instanceof Message) {
          if (stanza.hasExtension(ChatStateExtension.NAMESPACE)) {
            Intent intent = new Intent();
            intent.setAction("composing");
            intent.putExtra(stanza.getExtension(ChatStateExtension.NAMESPACE).getElementName(),
                stanza.getFrom());
            // sendBroadcast(intent);
          }
          if (((Message) stanza).getBody() != null) {
            return true;
          }
        }
        return false;
      }
    });

Add Stanza (Packet) acknowledgment listener-   

 mConnection.addStanzaAcknowledgedListener(new StanzaListener() {
      @Override public void processPacket(Stanza packet)
          throws SmackException.NotConnectedException {
        if (packet instanceof Message) {
          if (packet.getError() != null) {
            // Mark  Message un sent acknowledgment here
          } else {
            // Mark Message sent acknowledgment here
          }
        }
      }
    });

Connect with Openfire –

public void connect(final String caller) {

    AsyncTask<Void, Void, Boolean> connectionThread = new AsyncTask<Void, Void, Boolean>() {
      @Override protected synchronized Boolean doInBackground(Void... arg0) {
        if (mConnection.isConnected()) return false;
        isconnecting = true;
        Log.d("Connect() Function", caller + "=>connecting....");

        try {
          mConnection.connect();
         
          connected = true;
        } catch (IOException e) {

          Log.e("(" + caller + ")", "IOException: " + e.getMessage());
        } catch (SmackException e) {

          Log.e("(" + caller + ")", "SMACKException: " + e.getMessage());
        } catch (XMPPException e) {
          Log.e("connect(" + caller + ")", "XMPPException: " + e.getMessage());
        }
        return isconnecting = false;
      }
    };
    connectionThread.execute();
  }

Login in Openfire – 

 public void login() {

    try {
      mConnection.login(loginUser, passwordUser);
      // Set the status to available
      Presence presence = new Presence(Presence.Type.available);
      mConnection.sendPacket(presence);
      Log.i("LOGIN", "Yey! We're connected to the Xmpp server!" + loginUser);
    } catch (XMPPException | SmackException | IOException e) {
      e.printStackTrace();
    } catch (Exception e) {
    }
  }

Add Delivery Receipt with Message  

DeliveryReceiptManager deliveryReceiptManager =
    DeliveryReceiptManager.getInstanceFor(mConnection);
deliveryReceiptManager.autoAddDeliveryReceiptRequests();
deliveryReceiptManager.setAutoReceiptMode(DeliveryReceiptManager.AutoReceiptMode.always);
deliveryReceiptManager.addReceiptReceivedListener(new ReceiptReceivedListener() {
  @Override public void onReceiptReceived(String fromJid, String toJid, String receiptId,
      Stanza receipt) {

    // Mark delivered here

    Message message = new Message();
    message.setStanzaId(receipt.getStanzaId());
    //                message.setType(Message.Type.headline);
    try {
      ChatManager.getInstanceFor(mConnection)
          .createChat("admin" + MyCommunityChatService.JID_SUFFIX)
          .sendMessage(message);
    } catch (SmackException.NotConnectedException e) {

      e.printStackTrace();
    }
  }
});

Disconnect  with server 

public void disconnect() {
  new Thread(new Runnable() {
    @Override public void run() {
      mConnection.disconnect();
    }
  }).start();
}

Send One to One Message

  public void sendOneToOneMessage(ChatMessage message) {
    if (!chat_created) {
      oneToOneChat = ChatManager.getInstanceFor(mConnection).createChat(message.getReceiver());
      chat_created = true;
    }
    final Message chatMessage = new Message();
    chatMessage.setBody(message.toString());
    chatMessage.setStanzaId(message.getMsgid());
    chatMessage.setType(Message.Type.chat);
    try {
      oneToOneChat.sendMessage(chatMessage);
    } catch (SmackException.NotConnectedException e) {
      e.printStackTrace();
      disconnect();
      init();
    }
  }

Chat Message definition

public class ChatMessage {
  public String body, sender, receiver, senderName;
  public String Date, Time;
  public String msgid;
  public boolean isMine;// Did I send the message.

  public ChatMessage() {
  }

  public ChatMessage(String Sender, String Receiver, String messageString, String ID,
      boolean isMINE) {
    body = messageString;
    isMine = isMINE;
    sender = Sender;
    msgid = ID;
    receiver = Receiver;
    senderName = sender;
  }

  public static ChatMessage instanceOf(String messageString) {
    if (messageString == null) {
      return new ChatMessage();
    } else {
      return new Gson().fromJson(messageString, ChatMessage.class);
    }

  public void setMsgID() {

    msgid += "-" + String.format("%02d", new Random().nextInt(100));
  }

  public String getBody() {
    return body;
  }

  public void setBody(String body) {
    this.body = body;
  }

  public String getSender() {
    return sender;
  }

  public void setSender(String sender) {
    this.sender = sender;
  }

  public String getReceiver() {
    return receiver;
  }

  public void setReceiver(String receiver) {
    this.receiver = receiver;
  }

  public String getSenderName() {
    return senderName;
  }

  public void setSenderName(String senderName) {
    this.senderName = senderName;
  }

  public String getDate() {
    return Date;
  }

  public void setDate(String date) {
    Date = date;
  }

  public String getTime() {
    return Time;
  }

  public void setTime(String time) {
    Time = time;
  }

  public String getMsgid() {
    return msgid;
  }

  public void setMsgid(String msgid) {
    this.msgid = msgid;
  }

  public boolean isMine() {
    return isMine;
  }

  public void setMine(boolean mine) {
    isMine = mine;
  }
}

 

Now your complete code look like below code

public class XmppChatManager {
  public static boolean connected = false;
  public boolean loggedin = false;
  public static boolean isconnecting = false;
  private boolean chat_created = false;
  private String serverAddress;
  public static XMPPTCPConnection mConnection;
  public static String loginUser;
  public static String passwordUser;
  Gson gson;
  SmackService context;

  public static XmppChatManager instance = null;
  public static boolean instanceCreated = false;
  public static final String TAG = "Smack Service";

  public XmppChatManager(SmackService context, String serverAdress, String logiUser,
      String passwordser) {
    this.serverAddress = serverAdress;
    this.loginUser = logiUser;
    this.passwordUser = passwordser;
    this.context = context;
    init();
  }

  public static XmppChatManager getInstance(SmackService context, String server, String user,
      String pass) {

    if (instance == null) {
      instance = new XmppChatManager(context, server, user, pass);
      instanceCreated = true;
    }
    return instance;
  }

  public static org.jivesoftware.smack.chat.Chat oneToOneChat;
  public static MultiUserChat groupChat;

  static {
    try {
      Class.forName("org.jivesoftware.smack.ReconnectionManager");
    } catch (ClassNotFoundException ex) {
      // problem loading reconnection manager
    }
  }

  public void init() {
    gson = new Gson();
    //mMessageListener = new MMessageListener(context);
    //mChatManagerListener = new ChatManagerListenerImpl();
    initialiseConnection();
  }

  public static XMPPTCPConnection getConnection() {
    return mConnection;
  }

  private void initialiseConnection() {
    // Add SSL certificate
    SASLAuthentication.blacklistSASLMechanism("SCRAM-SHA-1");
    SASLAuthentication.blacklistSASLMechanism("DIGEST-MD5");
    SASLAuthentication.unBlacklistSASLMechanism("PLAIN");

    XMPPTCPConnectionConfiguration.Builder config = XMPPTCPConnectionConfiguration.builder();
    config.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled);
    config.setServiceName(MyCommunityChatService.XMPP_SERVICE_NAME);
    config.setResource(MyCommunityChatService.XMPP_SERVICE_NAME);

    config.setHost(serverAddress);
    config.setPort(5222);
    config.setDebuggerEnabled(true);

    XMPPTCPConnection.setUseStreamManagementResumptiodDefault(true);
    XMPPTCPConnection.setUseStreamManagementDefault(true);
    mConnection = new XMPPTCPConnection(config.build());
    XMPPConnectionListener connectionListener = new XMPPConnectionListener();
    mConnection.addConnectionListener(connectionListener);
    mConnection.setUseStreamManagement(true);

   // set packet reply timeout time
    mConnection.setPacketReplyTimeout(10000);

    // Add reconnect manager
    ReconnectionManager.getInstanceFor(mConnection).enableAutomaticReconnection();
    ServerPingWithAlarmManager.onCreate(context);
    ServerPingWithAlarmManager.getInstanceFor(mConnection).setEnabled(true);
    ReconnectionManager.setEnabledPerDefault(true);

    // Add ping manager here
    PingManager.getInstanceFor(mConnection).registerPingFailedListener(new PingFailedListener() {
      @Override public void pingFailed() {
        disconnect();
        initialiseConnection();
      }
    });
    addStanzaListner();
  }

  public void disconnect() {
    new Thread(new Runnable() {
      @Override public void run() {
        mConnection.disconnect();
      }
    }).start();
  }

  public void connect(final String caller) {

    AsyncTask<Void, Void, Boolean> connectionThread = new AsyncTask<Void, Void, Boolean>() {
      @Override protected synchronized Boolean doInBackground(Void... arg0) {
        if (mConnection.isConnected()) return false;
        isconnecting = true;
        Log.d("Connect() Function", caller + "=>connecting....");

        try {
          mConnection.connect();
          DeliveryReceiptManager deliveryReceiptManager =
              DeliveryReceiptManager.getInstanceFor(mConnection);
          deliveryReceiptManager.autoAddDeliveryReceiptRequests();
          deliveryReceiptManager.setAutoReceiptMode(DeliveryReceiptManager.AutoReceiptMode.always);
          deliveryReceiptManager.addReceiptReceivedListener(new ReceiptReceivedListener() {
            @Override public void onReceiptReceived(String fromJid, String toJid, String receiptId,
                Stanza receipt) {

              // Mark delivered here

              Message message = new Message();
              message.setStanzaId(receipt.getStanzaId());
              //                message.setType(Message.Type.headline);
              try {
                ChatManager.getInstanceFor(mConnection)
                    .createChat("admin" + MyCommunityChatService.JID_SUFFIX)
                    .sendMessage(message);
              } catch (SmackException.NotConnectedException e) {

                e.printStackTrace();
              }
            }
          });
          connected = true;
        } catch (IOException e) {

          Log.e("(" + caller + ")", "IOException: " + e.getMessage());
        } catch (SmackException e) {

          Log.e("(" + caller + ")", "SMACKException: " + e.getMessage());
        } catch (XMPPException e) {
          Log.e("connect(" + caller + ")", "XMPPException: " + e.getMessage());
        }
        return isconnecting = false;
      }
    };
    connectionThread.execute();
  }

  public void login() {

    try {
      mConnection.login(loginUser, passwordUser);
      // Set the status to available
      Presence presence = new Presence(Presence.Type.available);
      mConnection.sendPacket(presence);
      Log.i("LOGIN", "Yey! We're connected to the Xmpp server!" + loginUser);
    } catch (XMPPException | SmackException | IOException e) {
      e.printStackTrace();
    } catch (Exception e) {
    }
  }

  public void sendOneToOneMessage(ChatMessage message) {
    if (!chat_created) {
      oneToOneChat = ChatManager.getInstanceFor(mConnection).createChat(message.getReceiver());
      chat_created = true;
    }
    final Message chatMessage = new Message();
    chatMessage.setBody(message.toString());
    chatMessage.setStanzaId(message.getMsgid());
    chatMessage.setType(Message.Type.chat);
    try {
      oneToOneChat.sendMessage(chatMessage);
    } catch (SmackException.NotConnectedException e) {
      e.printStackTrace();
      disconnect();
      init();
    }
  }

  public class XMPPConnectionListener implements ConnectionListener {
    @Override public void connected(final XMPPConnection mConnection) {

      Log.d("xmpp", "Connected!");
      connected = true;
      if (!mConnection.isAuthenticated()) {
        login();
      }
    }

    @Override public void connectionClosed() {

      Log.d("xmpp", "ConnectionCLosed!");
      connected = false;
      chat_created = false;
      loggedin = false;
    }

    @Override public void connectionClosedOnError(Exception arg0) {

      Log.d("xmpp", "ConnectionClosedOn Error!");
      connected = false;
      chat_created = false;
      loggedin = false;
    }

    @Override public void reconnectingIn(int arg0) {

      Log.d("xmpp", "Reconnectingin " + arg0);
      loggedin = false;
      disconnect();
      initialiseConnection();
    }

    @Override public void reconnectionFailed(Exception arg0) {

      Log.d("xmpp", "ReconnectionFailed!");
      connected = false;
      chat_created = false;
      loggedin = false;
    }

    @Override public void reconnectionSuccessful() {
      Log.d("xmpp", "ReconnectionSuccessful");
      connected = true;
      chat_created = false;
      loggedin = false;
    }

    @Override public void authenticated(XMPPConnection arg0, boolean arg1) {
      Log.d("xmpp", "Authenticated!");
      loggedin = true;

      //      ChatManager.getInstanceFor(mConnection).addChatListener(mChatManagerListener);

      chat_created = false;
      new Thread(new Runnable() {

        @Override public void run() {
          try {
            Thread.sleep(500);
          } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
        }
      }).start();
    }
  }

  private void addStanzaListner() {
    mConnection.addAsyncStanzaListener(new StanzaListener() {
      private ChatMessage superMessage;
      private DelayInformation delayInformation;

      @Override public void processPacket(Stanza packet)
          throws SmackException.NotConnectedException {
        if (!packet.getFrom().contains(mConnection.getUser())) {
          Log.i("TAG", "processPacket: new packet received in service");
          superMessage = ChatMessage.instanceOf(((Message) packet).getBody());

          delayInformation = null;
          try {
            delayInformation = packet.getExtension("delay", "urn:xmpp:delay");
          } catch (Exception e) {
            e.printStackTrace();
          }
          if (delayInformation != null) {
            Date date = delayInformation.getStamp();
            // set up message delay information here
          }
          // Message receive here

        }
      }
    }, new StanzaFilter() {
      @Override public boolean accept(Stanza stanza) {
        if (stanza instanceof Message) {
          if (stanza.hasExtension(ChatStateExtension.NAMESPACE)) {
            Intent intent = new Intent();
            intent.setAction("composing");
            intent.putExtra(stanza.getExtension(ChatStateExtension.NAMESPACE).getElementName(),
                stanza.getFrom());
            // sendBroadcast(intent);
          }
          if (((Message) stanza).getBody() != null) {
            return true;
          }
        }
        return false;
      }
    });

    mConnection.addStanzaAcknowledgedListener(new StanzaListener() {
      @Override public void processPacket(Stanza packet)
          throws SmackException.NotConnectedException {
        if (packet instanceof Message) {
          if (packet.getError() != null) {
            // Mark  Message un sent acknowledgment here
          } else {
            // Mark Message sent acknowledgment here
          }
        }
      }
    });
  }
}

 

 Background Service that makes Connection alive. 

public class SmackService extends Service {

  private boolean mActive;
  private Thread mThread;
  private Handler mHandler;

  String userName="username52",password="Password123";
  private XmppChatManager xmppConnection;
  private static XMPPTCPConnection mConnection;

  public SmackService() {
  }

  public static void start(Context context) {
    Intent intent = new Intent(context, SmackService.class);
    context.startService(intent);
  }

  @Override public void onCreate() {
    super.onCreate();


  }

  @Override public int onStartCommand(Intent intent, int flags, int startId) {
    mConnection = XmppConnection.getConnection();
    if (isConnectingToInternet()) {
      start();
    }

    return Service.START_STICKY;
  }

  @Override public void onDestroy() {
    super.onDestroy();
    stop();
  }

  @Nullable @Override public IBinder onBind(Intent intent) {
    return null;
  }

  public void start() {
    if (!mActive) {
      mActive = true;

      // Create ConnectionThread Loop
      if (mThread == null || !mThread.isAlive()) {
        mThread = new Thread(new Runnable() {
          @Override public void run() {
            Looper.prepare();
            mHandler = new Handler();
            initConnection();
            Looper.loop();
          }
        });
        mThread.start();
      }
    }
  }

  public void stop() {
    mActive = false;
  }

  private void initConnection() {

    if (mConnection == null) {
      xmppConnection = XmppChatManager.getInstance(this, XMPP_HOST, userName, userName);
      xmppConnection.connect(userName);
    } else {

    }
  }

  public boolean isConnectingToInternet() {
    ConnectivityManager connectivity =
        (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
    if (connectivity != null) {
      NetworkInfo[] info = connectivity.getAllNetworkInfo();
      if (info != null) {
        for (int i = 0; i < info.length; i++)
          if (info[i].getState() == NetworkInfo.State.CONNECTED) {
            return true;
          }
      }
    }
    return false;
  }
}

 

  • Next step Code 

Related content

We Love Conversations

Say Hello
Go to Top