1. MQTT服务器搭建
点击[这里](http://activemq.apache.org/apollo/download.html),下载Apollo服务器,解压后安装(如果下载的是免安装版本,就直接辅助到C:\Program Files)中。
命令行进入安装目录bin目录下(例:C:\Program Files\apache-apollo-1.7.1\bin)。
输入apollo create G:\mqtt\apollo\myapollo(myapollo为创建的服务器实例名称),之后会在G:\mqtt\apollo目录下创建名称为myapollo的文件夹。myapollo文件夹下etc\apollo.xml文件下是配置服务器信息的文件。etc\users.properties文件包含连接MQTT服务器时用到的用户名和密码,默认为admin=password,即账号为admin,密码为password,可自行更改。
进入G:\mqtt\apollo\myapollo/bin目录,输入apollo-broker.cmd run开启服务器,看到如下界面代表搭建完成.
浏览器输入http://127.0.0.1:61680,进入如图所示的页面,输入admin和password,可以进入管理页面.
2.java服务端代码
服务端代码是一个简单的双向通讯实现,将输入框的输入内容发送到客户端中,接收客户端的消息显示在控制台中,具体代码如下所示.
package com.mqtt.server;
import java.awt.Container;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.UnsupportedEncodingException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttTopic;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
public class Server extends JFrame {
private static final long serialVersionUID = 1L;
private JPanel panel1;
private JPanel panel2;
private JButton button;
private JTextArea contentTextArea;
private MqttClient client;
private String host = "tcp://192.168.31.4:61613";
private String userName = "admin";
private String passWord = "password";
private MqttTopic topic;
private MqttMessage message;
private static String clientTopic = "clientTopic1";
private static String serverTopic = "serverTopic1";
private int currentQos = 2;
public Server() {
try {
client = new MqttClient(host, "Server", new MemoryPersistence());
connect();
} catch (Exception e) {
e.printStackTrace();
}
Container container = this.getContentPane();
panel1 = new JPanel();
panel2 = new JPanel();
contentTextArea = new JTextArea(10,50);
contentTextArea.setFocusable(true);
button = new JButton("发送");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
message = new MqttMessage();
message.setQos(currentQos);
message.setRetained(true);
try {
message.setPayload(contentTextArea.getText().toString().getBytes("UTF-8"));
} catch (UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println("send="+message.getPayload().toString());
try {
MqttDeliveryToken token = topic.publish(message);
token.waitForCompletion();
System.out.println("token.isComplete()="+token.isComplete() + "========");
} catch (Exception e) {
e.printStackTrace();
}
}
});
panel1.add(button);
panel2.add(contentTextArea);
container.add(panel2, "North");
container.add(panel1, "Center");
}
private void connect() {
MqttConnectOptions options = new MqttConnectOptions();
options.setCleanSession(false);
options.setUserName(userName);
options.setPassword(passWord.toCharArray());
//设置超时时间
options.setConnectionTimeout(10);
//设置心跳时间
options.setKeepAliveInterval(20);
try {
client.setCallback(new MqttCallback() {
@Override
public void connectionLost(Throwable cause) {
connectState = false;
System.out.println("connectionLost-----------");
}
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
System.out.println("deliveryComplete---------" + token.isComplete());
}
@Override
public void messageArrived(String topic, MqttMessage arg1) throws Exception {
System.out.println("messageArrived----------");
String str = new String(arg1.getPayload(),"UTF-8");
System.out.println("receive----------"+str);
}
});
topic = client.getTopic(serverTopic);
client.connect(options);
client.subscribe(clientTopic,currentQos);
} catch (Exception e) {
System.out.println("Exception----------"+e.getMessage());
e.printStackTrace();
}
}
public static void main(String[] args) {
Server s = new Server();
s.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
s.setSize(600, 370);
s.setLocationRelativeTo(null);
s.setVisible(true);
}
}
3.Android客户端实现
客户端的代码是从其他的项目中截取过来的,基本方法都实现了,但是有点不完整,仅供参考,没法直接复制来使用,敬请谅解,代码如下所示:
package com.angite.mqtt;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.IBinder;
import com.google.gson.Gson;
import com.angite.log.LogTool;
import com.angite.mqtt.model.MqttData;
import com.angite.mqtt.model.MqttSend;
import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.persist.MqttDefaultFilePersistence;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import de.greenrobot.event.EventBus;
import de.greenrobot.event.Subscribe;
import de.greenrobot.event.ThreadMode;
/**
* Created by admin on 2017-10-24.
*/
public class MQTTService extends Service {
public static final String TAG = MQTTService.class.getSimpleName();
private MqttAndroidClient client;
private MqttConnectOptions conOpt;
private String host = "tcp://192.168.31.4:61613";
private String userName = "admin";
private String passWord = "password";
private static String clientTopic = "clientTopic1";
private static String serverTopic = "serverTopic1";
private String clientId = "6210817200012232";
private int currentQos = 2;
@Override
public void onCreate() {
super.onCreate();
EventBus.getDefault().register(this);
}
//订阅方法,当接收到事件的时候,会调用该方法
@Subscribe(threadMode = ThreadMode.BackgroundThread)
public void onMqttEvent(MqttSend mqttSend){
publish(mqttSend.getMessage());
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
LogTool.log("MQTTService","onStartCommand");
init();
return super.onStartCommand(intent, flags, startId);
}
private void publish(String msg){
LogTool.log("MQTTService","publish="+msg);
String topic = clientTopic;
MqttMessage mqttMessage = new MqttMessage();
mqttMessage.setQos(currentQos);
mqttMessage.setRetained(true);
try {
mqttMessage.setPayload(msg.getBytes("UTF-8"));
client.publish(topic,mqttMessage);
} catch (Exception e) {
e.printStackTrace();
}
}
private void init() {
// 服务器地址(协议+地址+端口号)
String uri = host;
client = new MqttAndroidClient(this, uri, clientId);
// 设置MQTT监听并且接受消息
client.setCallback(mqttCallback);
conOpt = new MqttConnectOptions();
// 清除缓存
conOpt.setCleanSession(true);
// 设置超时时间,单位:秒
conOpt.setConnectionTimeout(10);
// 心跳包发送间隔,单位:秒
conOpt.setKeepAliveInterval(20);
// 用户名
conOpt.setUserName(userName);
// 密码
conOpt.setPassword(passWord.toCharArray());
// last will message
boolean doConnect = true;
String message = "{\"terminal_uid\":\"" + clientId + "\"}";
String topic = serverTopic;
Integer qos = currentQos;
Boolean retained = true;
if ((!message.equals("")) || (!topic.equals(""))) {
// 最后的遗嘱
try {
conOpt.setWill(topic, message.getBytes(), qos.intValue(), retained.booleanValue());
} catch (Exception e) {
LogTool.log(TAG, "Exception Occured"+e.getMessage());
doConnect = false;
iMqttActionListener.onFailure(null, e);
}
}
if (doConnect) {
doClientConnection();
}
}
@Override
public void onDestroy() {
try {
client.disconnect();
} catch (MqttException e) {
e.printStackTrace();
}
super.onDestroy();
}
/** 连接MQTT服务器 */
private void doClientConnection() {
if (!client.isConnected() && isConnectIsNomarl()) {
try {
client.connect(conOpt, null, iMqttActionListener);
} catch (MqttException e) {
e.printStackTrace();
}
}
}
// MQTT是否连接成功
private IMqttActionListener iMqttActionListener = new IMqttActionListener() {
@Override
public void onSuccess(IMqttToken arg0) {
LogTool.log(TAG, "连接成功 ");
try {
// 订阅myTopic话题
client.subscribe(serverTopic,currentQos);
} catch (MqttException e) {
e.printStackTrace();
}
publish("连接成功");
}
@Override
public void onFailure(IMqttToken arg0, Throwable arg1) {
arg1.printStackTrace();
// 连接失败,重连
LogTool.log(TAG, "连接失败 ");
}
};
private Gson gson = new Gson();
// MQTT监听并且接受消息
private MqttCallback mqttCallback = new MqttCallback() {
@Override
public void messageArrived(String topic, org.eclipse.paho.client.mqttv3.MqttMessage message) throws Exception {
try {
String str = new String(message.getPayload(), "utf-8");
LogTool.log(TAG, str);
MqttData mqttData = gson.fromJson(str, MqttData.class);
MqttTool.mqttDataParse(mqttData);
}catch(Exception e){
LogTool.log("mqtt--"+e.getMessage());
e.printStackTrace();
}
}
@Override
public void deliveryComplete(IMqttDeliveryToken arg0) {
LogTool.log(TAG, "deliveryComplete");
}
@Override
public void connectionLost(Throwable arg0) {
// 失去连接,重连
LogTool.log(TAG, "连接失败 ");
}
};
/** 判断网络是否连接 */
private boolean isConnectIsNomarl() {
ConnectivityManager connectivityManager = (ConnectivityManager) this.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = connectivityManager.getActiveNetworkInfo();
if (info != null && info.isAvailable()) {
String type = info.getTypeName();
LogTool.log(TAG, "MQTT当前网络类型:" + type);
return true;
} else {
LogTool.log(TAG, "MQTT 没有可用网络");
return false;
}
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
这份代码是使用Android Studio生成的,所需的库通过build.gradle来引用进来,如下所示
compile 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.0'
compile 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.0'
compile 'de.greenrobot:eventbus:3.0.0-beta1'
本文是综合了网上好几个小伙伴的博客和自己的一些理解实践完成的,谢谢大家支持