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/…