Android消息推送之MQTT

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);
    }
}

代码所需的jar请点击这里下载

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'

这里使用了EventBus3.0发送消息,感兴趣的可以看下EventBus3.0使用及源码解析

本文是综合了网上好几个小伙伴的博客和自己的一些理解实践完成的,谢谢大家支持

关于Mqtt具体介绍可以参考这篇博客:Android APP必备高级功能,消息推送之MQTT 一口仨馍

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值