Android系统资源预置
Android – MQTT协议
开篇
MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的"轻量级"通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布。
MQTT是一个基于客户端-服务器的消息发布/订阅传输协议。
MQTT 链接服务器
1.导入MQTT包:
//导入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'
2.MQTT管理类:
public class MQTTManager {
public static final String SERVER_HOST = "tcp://##.##.###.###:####"; //使用自己的服务器地址名称
private static final String TAG= "MQTTManager";
private Context mContext;
private static MQTTManager mqttManager=null;
private MqttAndroidClient client;
private MqttConnectOptions mMqttConnectOptions;
private MessageHandlerCallBack callBack;
private MTQQService mTQQService;
private volatile BlockingDeque<BaseCommand> commandBlockingDeque;
private boolean mIsBindService = false;
public static String PUBLISH_TOPIC = TopicData.TOPIC_UP;//发布主题
public static String RESPONSE_TOPIC = LauncherApp.setIMEI();//订阅主题
private MQTTManager (Context context){
mContext=context;
}
/**
* 获取一个MQTTManager单例
* @param context
* @return 返回一个MQTTManager的实例对象
*/
public static MQTTManager getInstance(Context context) {
UtilLog.i(TAG,"mqttManager="+mqttManager);
if (mqttManager==null) {
mqttManager=new MQTTManager(context);
synchronized (Object.class) {
UtilLog.i(TAG,"synchronized mqttManager="+mqttManager);
if (mqttManager!=null) {
return mqttManager;
}
}
}else {
UtilLog.i(TAG,"else mqttManager="+mqttManager);
return mqttManager;
}
return null;
}
/**
* 订阅消息
* @param topic 订阅消息的主题
*/
public void subscribeMsg(String topic,int qos){
if (client != null && client.isConnected()) {
int[] Qos = {qos};
String[] topic1 = {topic};
try {
client.subscribe(topic1, Qos);
UtilLog.i(TAG,"开始订阅topic="+topic);
} catch (MqttException e) {
e.printStackTrace();
}
}
}
public void MQTTinit() {
UtilLog.i(TAG, "---YMX------init() ----");
UtilLog.i(TAG, "---YMX------init() -try ----");
String serverURI = SERVER_HOST; //服务器地址(协议+地址+端口号)
client = new MqttAndroidClient(mContext, serverURI, MTQQConstant.CLIENT);
client.setCallback(mqttCallback); //设置监听订阅消息的回调
mMqttConnectOptions = new MqttConnectOptions();
mMqttConnectOptions.setCleanSession(true); //设置是否清除缓存
mMqttConnectOptions.setConnectionTimeout(10*60); //设置超时时间,单位:秒
mMqttConnectOptions.setKeepAliveInterval(5*60); //设置心跳包发送间隔,单位:秒
mMqttConnectOptions.setUserName("admin"); //设置用户名
mMqttConnectOptions.setPassword("password".toCharArray()); //设置密码
boolean doConnect = true;
if (doConnect) {
UtilLog.i(TAG, "---YMX------doConnect() ----");
doClientConnection();
}
}
//订阅主题的回调
private MqttCallback mqttCallback = new MqttCallback() {
@Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
UtilLog.i(TAG, "Client 接收消息主题 :------"+ topic);
UtilLog.i(TAG, "Client 接收消息Qos-------"+ message.getQos());
UtilLog.i(TAG, "Client 接收消息内容------ :"+ new String(message.getPayload()));
String Data= new String(message.getPayload());
UtilLog.i(TAG, "---YMX------mqttCallback ----Data----"+Data);
ParseMTQQHelper.parse(Data);
// response("message arrived");
}
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
}
@Override
public void connectionLost(Throwable arg0) {
UtilLog.i(TAG, "---YMX------断开链接服务器 ----");
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
doClientConnection();//连接断开,重连
UtilLog.d(TAG, "---------IMqttActionListener------订阅"+RESPONSE_TOPIC+"---qos = --0---");
}
}, 10000);//3秒后执行Runnable中的run方法
}
};
/**
* 连接MQTT服务器
*/
private void doClientConnection() {
UtilLog.i(TAG, "---YMX------doClientConnection()开始链接服务器 ----");
if (!client.isConnected() && isConnectIsNomarl()) {
try {
UtilLog.i(TAG, "---YMX------client.connect(mMqttConnectOptions) ----");
client.connect(mMqttConnectOptions,null,iMqttActionListener);
} catch (MqttException e) {
e.printStackTrace();
}
}
}
/**
* 判断网络是否连接
*/
private boolean isConnectIsNomarl() {
ConnectivityManager connectivityManager = (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = connectivityManager.getActiveNetworkInfo();
if (info != null && info.isAvailable()) {
String name = info.getTypeName();
// Log.i(TAG, "当前网络名称:" + name);
return true;
} else {
// Log.i(TAG, "没有可用网络");
/*没有可用网络的时候,延迟3秒再尝试重连*/
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
doClientConnection();
}
}, 30000);
return false;
}
}
//MQTT是否连接成功的监听
private IMqttActionListener iMqttActionListener = new IMqttActionListener() {
@Override
public void onSuccess(IMqttToken arg0) {
UtilLog.d(TAG, "---------IMqttActionListener-------------连接成功 ");
if (RESPONSE_TOPIC!=null){
subscribeMsg(RESPONSE_TOPIC, 0);
AutoHrBtGpsUtil.getInstance().senStandard();
UtilLog.d(TAG, "---------IMqttActionListener------订阅"+RESPONSE_TOPIC+"---qos = --0---");
}else {
UtilLog.d(TAG, "---------IMqttActionListener------订阅"+RESPONSE_TOPIC+"---为空执行延时操作-");
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
RESPONSE_TOPIC= Util.getIMEI(LauncherApp.getAppContext());
subscribeMsg(RESPONSE_TOPIC, 0);
AutoHrBtGpsUtil.getInstance().senStandard();
UtilLog.d(TAG, "---------IMqttActionListener------订阅"+RESPONSE_TOPIC+"---qos = --0---");
}
}, 3000);//3秒后执行Runnable中的run方法
}
UtilLog.d(TAG, "---------IMqttActionListener------订阅"+RESPONSE_TOPIC+"---qos = --0---");
}
@Override
public void onFailure(IMqttToken arg0, Throwable arg1) {
arg1.printStackTrace();
UtilLog.d(TAG, "连接失败 ");
doClientConnection();//连接失败,重连(可关闭服务器进行模拟)
}
};
/**
* 发布消息
* @param topic 发布消息主题
* @param msg 消息体
* @param isRetained 是否为保留消息
*/
public void publish(String topic, base msg, boolean isRetained, int qos) {
try {
if (client!=null && client.isConnected()) {
Log.e(TAG, "publish:-------------YMX----------client "+ client );
MqttMessage message = new MqttMessage();
message.setQos(qos);
message.setRetained(isRetained);
message.setPayload(msg.toString().getBytes());
client.publish(topic, message);
UtilLog.i(TAG,"topic="+topic+"--msg="+msg.toString()+"--isRetained"+isRetained);
}else if(client!=null && !client.isConnected()){
doClientConnection();
}
} catch (MqttPersistenceException e) {
e.printStackTrace();
} catch (MqttException e) {
e.printStackTrace();
}
}
/**
* 断开链接
*/
public void disconnect(){
UtilLog.i(TAG, "---YMX------disconnect: ----");
if (client!=null &&client.isConnected()) {
try {
client.disconnect();
mqttManager=null;
} catch (MqttException e) {
e.printStackTrace();
}
}
}
/**
* 释放资源
*/
public void release(){
if (mqttManager!=null) {
mqttManager=null;
}
}
/**
* 判断服务是否连接
* @return
*/
public boolean isConnected(){
UtilLog.i(TAG, "---YMX------isConnected: ----");
if (client!=null) {
return client.isConnected();
}
return false;
}
}
3.调用 MQTTinit() 方法就能实现链接服务器,订阅主题。
个人使用方案
- 个人项目是一个手表项目对接协议的。就直接在launcher中,写一个Service启动MQTTinit()方法,然后在Application的onCreate()方法中调用。
遇到的坑
1.mqtt协议频繁中断,频繁重连。
中断原因: clientld 重复。可以使用UUID生成随机数。
2。后续可能还会更新一些问题。