利用MQTT可以做一个简单的聊天系统.
首先是加入依赖
//消息协议 implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.0' implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'
直接上类MQ管理类,用Timetask,30秒进行一次检测连接状态.断开就重连.需要注意的是,每个手机连接的clientId应该是不能变的,要不就会出现重复收到消息之类的各种BUG.
public class MQTTManager {
private static final String TAG = "MQTTManager";
private String clientId = "android_client";
private static MQTTManager mqttManager = null;
private MqttClient client;
private MqttConnectOptions options;
//private Context mContext;
private MessageHandlerCallBack callBack;
private MsgPublishListener publishListener;
private MQConnectListener connectListener;
private TimerTask task;
private Timer timer;
private MQTTManager() {
//mContext = context;
//这是保证每个手机使用同一个clientId的,自己处理
//if (MagicUtil.isEmpty(UserInfoManager.getInstance().getMQId())) {
// clientId = clientId + MqttClient.generateClientId();
//} else {
// clientId = UserInfoManager.getInstance().getMQId();
//}
}
/**
* 获取一个MQTTManager单例
*
* @return 返回一个MQTTManager的实例对象
*/
public static MQTTManager getInstance() {
if (mqttManager == null) {
synchronized (MQTTManager.class) {
if (mqttManager == null) {
mqttManager = new MQTTManager();
}
}
}
return mqttManager;
}
private NetChangeReceiver mNetChangeReceiver;
private Context unregisterContext;
public void setNetReceiver(Context context) {
IntentFilter filter = new IntentFilter();
//filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
//filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
mNetChangeReceiver = new NetChangeReceiver();
context.registerReceiver(mNetChangeReceiver, filter);
unregisterContext = context;
}
//解除网络变化监听
public void unregisterNet() {
if (mNetChangeReceiver != null && unregisterContext != null) {
unregisterContext.unregisterReceiver(mNetChangeReceiver);
mNetChangeReceiver = null;
unregisterContext = null;
}
}
/**
* 连接服务器
*/
public void connect() {
ThreadManage.getInstance().execute(new Runnable() {
@Override
public void run() {
Log.d(TAG, "开始连接MQtt");
try {
if (isConnected()) {
Log.d(TAG, "已连接过了");
if (connectListener != null) {
connectListener.success(true);
}
return;
}
// host为主机名,clientId即连接MQTT的客户端ID,一般以唯一标识符表示,MemoryPersistence设置clientid的保存形式,默认为以内存保存
client = new MqttClient("tcp:192.168.1.20:1883", clientId, new MemoryPersistence());
// MQTT的连接设置
options = new MqttConnectOptions();
// 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录,这里设置为true表示每次连接到服务器都以新的身份连接
options.setCleanSession(true);
// 设置连接的用户名
options.setUserName("admin");
// 设置连接的密码
options.setPassword("public".toCharArray());
// 设置超时时间 单位为秒
options.setConnectionTimeout(30);
// 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制
options.setKeepAliveInterval(30);
// 设置回调
// MqttTopic topic = client.getTopic(TOPIC);
//setWill方法,如果项目中需要知道客户端是否掉线可以调用该方法。设置最终端口的通知消息
//options.setWill(topic, "close".getBytes(), 2, true);
//SSLSocketFactory sslSocketFactory = null;
/* try {
sslSocketFactory = sslContextFromStream(mContext.getAssets().open("server.pem")).getSocketFactory();
} catch (Exception e) {
e.printStackTrace();
}
options.setSocketFactory(sslSocketFactory);*/
client.setCallback(new PushCallback());
client.connect(options);
if (client.isConnected() && connectListener != null) {
connectListener.success(true);
startCheck();
//UserInfoManager.getInstance().putMQId(clientId);
}
Log.d(TAG, "ClientId=" + client.getClientId());
} catch (MqttException e) {
e.printStackTrace();
Log.e(TAG, "connect: " + e);
}
}
});
}
private void startCheck() {
if (timer == null) {
timer = new Timer();
}
if (task == null) {
task = new TimerTask() {
@Override
public void run() {
MagicLog.d("开始检测MQ=========");
if (isConnected()) {
MagicLog.d("状态正常=========");
} else {
MagicLog.d("连接断开=========");
connect();
}
}
};
timer.schedule(task, 50, 30*1000); //30秒检测一次连接状态,断开就重连
MagicLog.d("========================起动检测MQTT=======================");
}
}
/**
* 订阅消息
*
* @param topic 订阅消息的主题
*/
public void subscribeMsg(String topic, int qos) {
if (client != null) {
int[] Qos = {qos};
String[] topic1 = {topic};
try {
client.subscribe(topic1, Qos);
MagicLog.d("开始订阅topic: " + topic);
} catch (MqttException e) {
e.printStackTrace();
}
}
}
/**
* 发布消息
*
* @param topic 发布消息主题
* @param msg 消息体
* @param isRetained 是否为保留消息
*/
public void publish(String topic, String msg, boolean isRetained, int qos) {
try {
if (client != null) {
MqttMessage message = new MqttMessage();
message.setQos(qos);
message.setRetained(isRetained);
message.setPayload(msg.getBytes());
client.publish(topic, message);
MagicLog.d("发布消息:" + msg);
}
} catch (MqttException e) {
e.printStackTrace();
if (callBack != null) {
publishListener.messagePublishOk(false);
}
}
}
int count = 0;
/**
* 发布和订阅消息的回调
*/
public class PushCallback implements MqttCallback {
public void connectionLost(Throwable cause) {
MagicLog.e("------connectionLost: " + cause);
/*if (count < 5) {
count++;//5次重连
MagicLog.d("断开连接,重新连接" + count + "次" + cause);
try {
client.close();
connect();
} catch (MqttException e) {
e.printStackTrace();
}
}*/
}
/**
* 发布消息的回调
*/
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
//publish后会执行到这里
//MagicLog.d("发布消息成功的回调" + token.isComplete());
if (publishListener != null) {
publishListener.messagePublishOk(token.isComplete());
}
}
/**
* 接收消息的回调方法
*/
@Override
public void messageArrived(final String topicName, final MqttMessage message) throws Exception {
//subscribe后得到的消息会执行到这里面
MagicLog.d("接收到消息:" + new String(message.getPayload()));
if (callBack != null) {
callBack.messageArrived(topicName, new String(message.getPayload()));
}
}
}
/**
* 设置接收消息的回调方法
*
* @param callBack
*/
public void setMessageHandlerCallBack(MessageHandlerCallBack callBack) {
this.callBack = callBack;
}
public void setConnectListener(MQConnectListener connectListener) {
this.connectListener = connectListener;
}
public void setPublishListener(MsgPublishListener publishListener) {
this.publishListener = publishListener;
}
/**
* 断开链接
*/
public void disconnect() {
if (client != null && client.isConnected()) {
try {
client.disconnect();
release();
mqttManager = null;
} catch (MqttException e) {
e.printStackTrace();
}
}
}
/**
* 释放资源
*/
private void release() {
if (task != null) {
task.cancel();
task = null;
}
if (timer != null) {
timer.purge();
timer.cancel();
timer = null;
}
}
/**
* 判断服务是否连接
*
* @return
*/
public boolean isConnected() {
if (client != null) {
return client.isConnected();
}
return false;
}
public SSLContext sslContextFromStream(InputStream inputStream) throws Exception {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
Certificate certificate = certificateFactory.generateCertificate(inputStream);
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", certificate);
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
return sslContext;
}
public interface MessageHandlerCallBack {
void messageArrived(String topicName, String content);
}
public interface MsgPublishListener{
void messagePublishOk(boolean isOk);
}
监听网络变化类:
public class NetChangeReceiver extends BroadcastReceiver {
private int count = 0;
@Override
public void onReceive(Context context, Intent intent) {
if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
//MagicLog.d("===================网络改变==================");
//进行网络验证
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isAvailable()) {
MagicLog.d("===================网络可用");
if (count != 0) {
MagicLog.d("===================网络可用,开始连接MQTTManager==================");
MQTTManager manager = MQTTManager.getInstance();
manager.connect();
}
//EventBus.getDefault().post(new EventNetChange(true));
} else {
MagicLog.d("===================网络不可用==================");
//EventBus.getDefault().post(new EventNetChange(false));
}
//MagicLog.d("===================网络变化count==================:" + 0);
count++;
}
}
}
最后就是使用了.进入主页调用:
private MQTTManager mMqttManager;
private void initMQ() {
mMqttManager = MQTTManager.getInstance();
mMqttManager.connect();
mMqttManager.setNetReceiver(this);
mMqttManager.setConnectListener(connect ->
subscribeMessage()
);
}
//订阅消息
private void subscribeMessage() {
mMqttManager.subscribeMsg(UserInfoManager.getInstance().getTopicServer(), 2);
mMqttManager.setMessageHandlerCallBack((topicName, content) -> {
try {
//获取到消息
} catch (JSONException e) {
e.printStackTrace();
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mMqttManager != null) {
mMqttManager.unregisterNet();
mMqttManager.disconnect();
}
}