The server uses Openfire and the Android client uses Asmack.jar, but Asmack is now out of maintenance and Openfire and its companion Smack.jar are constantly updated. So this blog is mainly about how to use the latest openfire4.5.1+smack4.3.4 to complete the initial implementation of XMPP!

The effect is shown below:

The above is for Spark on the Android client and PC to implement instant chat, of course mobile phone to mobile phone chat. The related resources download address: igniterealtime.org/downloads/i…

As for the installation method of Openfire, it is basically the same as before. Please refer to the introduction in the previous article. Before using Openfire, please install the database well.

Database (custom database name) :

The installation is successful!

Start writing android apps!

The methods in Smack.jar are similar to and different from previous asmack methods. First, Smack’s latest login methods are as follows:

                    InetAddress addr = InetAddress.getByName(Const.XMPP_HOST);
                    HostnameVerifier verifier = new HostnameVerifier() {
                        @Override
                        public boolean verify(String hostname, SSLSession session) {
                            return false; }}; DomainBareJid serviceName = JidCreate.domainBareFrom(Const.XMPP_DOMAIN);//Domain server name
                    XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder()
                            .setHost(Const.XMPP_HOST)
                            .setPort(5222)
                            .setSecurityMode(ConnectionConfiguration.SecurityMode.disabled)
                            .setXmppDomain(serviceName)
                            .setHostnameVerifier(verifier)
                            .setHostAddress(addr)
                            .setConnectTimeout(30000)
                            .build();
                    xmpptcpConnection = new XMPPTCPConnection(config);
                    // Enable reconnection
// ReconnectionManager reconnectionManager = ReconnectionManager.getInstanceFor(xmpptcpConnection);
// reconnectionManager.setFixedDelay(5);
// reconnectionManager.enableAutomaticReconnection();
                    / / the connection
                    xmpptcpConnection.connect();
                    / / login
                    xmpptcpConnection.login(PreferencesUtils.getSharePreStr(context, Const.ACCOUNT), PreferencesUtils.getSharePreStr(context, Const.PWD));
                    if (xmpptcpConnection.isAuthenticated()) {// Login succeeded
                       
                    } else {// Login failed
                      
                    }
Copy the code

Port 5222 is fixed, and two other important parameters: host Domain name and Domain server name: This is set when openFire is installed:

Here I have set the two names the same!

To register methods, simply call the following methods after connect is successful:

AccountManager accountManager = AccountManager.getInstance(xmpptcpConnection);
accountManager.sensitiveOperationOverInsecureConnection(true);
accountManager.createAccount(Localpart.from(username), pwd);
Copy the code

Note that methods such as XMPP connections need to be done in threads, remember!

AddConnectionListener:

    ConnectionListener connectionListener = new ConnectionListener() {
        @Override
        public void connected(XMPPConnection connection) {
          
        }

        @Override
        public void authenticated(XMPPConnection connection, boolean resumed) {

        }

        @Override
        public void connectionClosed() {

        }

        @Override
        public void connectionClosedOnError(Exception e){}};Copy the code

Listen for message reception:

ChatManager.getInstanceFor(xmpptcpConnection).addIncomingListener(new IncomingChatMessageListener() {
        @Override
        public void newIncomingMessage(EntityBareJid from, Message message, Chat chat){}})Copy the code

Monitor message sending:

ChatManager.getInstanceFor(xmpptcpConnection).addOutgoingListener(new OutgoingChatMessageListener() {
        @Override
        public void newOutgoingMessage(EntityBareJid from, Message message, Chat chat){}})Copy the code

Send a message:

 EntityBareJid jid = JidCreate.entityBareFrom(to + "@" + Const.XMPP_DOMAIN);
 Chat chat = XMPPConnectionUtil.getChatManager().chatWith(jid);
  if(chat ! =null) {
      Message message = new Message();
      message.setBody(msg);
      chat.send(message);
  }
Copy the code

Receive offline messages: First look at the above login method has Settings:

.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled)
Copy the code

This method indicates that the user logs in offline, so that the user can receive offline messages. After the login is successful:

 OfflineMessageManager offlineMessageManager = new OfflineMessageManager(XMPPConnectionUtil.getInstance());
                List<Message> messageList = offlineMessageManager.getMessages();
                for (Message message : messageList) {
                    LogUtil.e("Offline Message >>" + message.getBody());
                }
                offlineMessageManager.deleteMessages();
                XMPPConnectionUtil.getInstance().sendStanza(new Presence(Presence.Type.available));
Copy the code

After the offline message is obtained, the login status is set to online available.

Since the reconnection mechanism built-in with Smack is not easy to use, we need to write a reliable reconnection mechanism ourselves. We need to listen in ConnectionListener. Once a connection error is found, the reconnection mechanism will be enabled.

    @SuppressLint("HandlerLeak")
    public Handler handler = new Handler() {
        @Override
        public void handleMessage(@NonNull android.os.Message msg) {
            super.handleMessage(msg);
            LogUtil.e("Reconnect >>");
            XMPPConnectionUtil.login(mContext, new XMPPConnectionUtil.OnLoginListener() {
                @Override
                public void onLogin(boolean isLogin, String error) {
                    if(! TextUtils.isEmpty(error) && error.contains("already logged")) {
                        handler.removeMessages(0);
                        return;
                    }
                    if (isLogin) {// The connection succeeded
                        LogUtil.e("Connection successful >>");
                        XMPPConnectionUtil.getInstance().addConnectionListener(connectionListener);
                        XMPPConnectionUtil.getChatManager().addIncomingListener(incomingChatMessageListener);
                        XMPPConnectionUtil.getChatManager().addOutgoingListener(outgoingChatMessageListener);
                        handler.removeMessages(0);
                    } else {
                        LogUtil.e("Connection failed >>");
                        handler.sendEmptyMessageDelayed(0.5000); }}}); }};/** * connection status monitor */
    ConnectionListener connectionListener = new ConnectionListener() {
        @Override
        public void connected(XMPPConnection connection) {
            handler.removeMessages(0);
            LogUtil.e("connected>>");
        }

        @Override
        public void authenticated(XMPPConnection connection, boolean resumed) {
            handler.removeMessages(0);
            LogUtil.e("authenticated>>" + resumed);
        }

        @Override
        public void connectionClosed() {
            removeListener();
            handler.sendEmptyMessage(0);
            LogUtil.e("connectionClosed>>");
        }

        @Override
        public void connectionClosedOnError(Exception e) {
            removeListener();
            handler.sendEmptyMessage(0);
            LogUtil.e("connectionClosedOnError>>"+ e.getMessage()); }};Copy the code

The project also includes methods to query users and friends, simple basic encapsulation, keeping XmppConnect object singleton mode. In addition, I write methods to receive messages and monitor connection status in MainActivity instead of Service as before, because Service management is more and more strict. It’s easy to kill even when the application is open, so write in ManActivity to make sure it’s as safe as possible!

GitHub:github.com/baiyuliang/…