android MQTT的使用及demo

概述:

Message Queuing Telemetry Transport,意为消息队列遥测传输,是IBM开发的一个即时通讯协议。.
功能是共用一个服务器,所有客户端只要订阅了同一个topic,只要其中一个publish,则其他所有订阅了的客户端都能收到推送的消息

demo下载地址:

https://download.csdn.net/download/u010672559/10549277

==============
1.服务器部署
http://activemq.apache.org/apollo/download.html 下载版本地址介绍
http://mirrors.tuna.tsinghua.edu.cn/apache/activemq/activemq-apollo/1.7.1/apache-apollo-1.7.1-windows-distro.zip具体下载地址
1.1下载后安装
1.2cmd命令行进入安装目录bin目录下(例:E:>cd E:\MQTT\apache-apollo-1.7.1\bin)。
1.3输入apollo create XXX(xxx为创建的服务器实例名称,例:apollo create mybroker),之后会在bin目录下创建名称为XXX的文件夹。XXX文件夹下etc\apollo.xml文件下是配置服务器信息的文件。etc\users.properties文件包含连接MQTT服务器时用到的用户名和密码,默认为admin=password,即账号为admin,密码为password,可自行更改。
1.4进入XXX/bin目录,输入apollo-broker.cmd run开启服务器,看到如下界面代表搭建完成,注意运行apollo-broker.cmd run是在自己create的mybroker下执行

2.客户端实现
基本概念:
topic:中文意思是“话题”。在MQTT中订阅了(subscribe)同一话题(topic)的客户端会同时收到消息推送。直接实现了“群聊”功能。
clientId:客户身份唯一标识。
qos:服务质量。
retained:要保留最后的断开连接信息。
MqttAndroidClient#subscribe():订阅某个话题。
MqttAndroidClient#publish(): 向某个话题发送消息,之后服务器会推送给所有订阅了此话题的客户。
userName:连接到MQTT服务器的用户名。
passWord :连接到MQTT服务器的密码。
2.1工程配置
2.1.1project下的build.gradle下面加
repositories {
    ...
    maven {
        url "https://repo.eclipse.org/content/repositories/paho-releases/"
    }
}
2.1.2module下的build.gradle下面加,eventbus非配置必须,实际是用户后面通信用
implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.0'
implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'
implementation 'org.greenrobot:eventbus:3.0.0'
2.1.3清单添加权限及注册service
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

<!-- Mqtt Service org.eclipse.paho.android.service.MqttService为依赖自带的,MQTTService为自己新建的->
<service android:name="org.eclipse.paho.android.service.MqttService" />
<service android:name=".MQTTService"/>
2.2实现代码
代码实现注意事项:
1.首先初始化各个参数,之后连接服务器。连接成功之后在http://127.0.0.1:61680/看到自动创建了名称为”topic”的topic。这里我使用了一个真机和一个模拟器运行程序。http://127.0.0.1:61680/服务端看到的是这个样子

2 模拟器运行的时候host = "tcp://10.0.2.2:61613",因为10.0.2.2 是模拟器设置的特定ip,是你电脑的别名。真机运行的时候host = "tcp://192.168.1.103:61613"。192.168.1.103是我主机的IPv4地址,查看本机IP的cmd命令为ipconfig/all。 
3.两次运行时的clientId不能一样(为了保证客户标识的唯一性)。
4.实际运行的时候模拟器客户端用tcp://10.0.2.2:61613,真机用的host不是自己手机的ip地址,而是电脑端的ip地址,因为服务器部署是在电脑上面部署的,且每个客户端的clientid要不同,但是topic要相同,否则其他客户端会收不到消息!!!!!
TelephonyManager mTm = (TelephonyManager)this.getSystemService(TELEPHONY_SERVICE);  
TelephonyIMEI = mTm.getDeviceId()
手机的IMEI号
5.实际效果是任意一个客户端点击了之后会publish内容出去,所有的客户端都会接收到消息,然后toast提示
MQTTService代码
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 android.support.annotation.Nullable;
import android.util.Log;

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.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.greenrobot.eventbus.EventBus;

/**
 * MQTT长连接服务
 *
 * @author 一口仨馍 联系方式 : [email protected]
 * @version 创建时间:2016/9/16 22:06
 */
public class MQTTService extends Service {

    public static final String TAG = MQTTService.class.getSimpleName();
//    public static final String TAG = "xiaozheng";

    private static MqttAndroidClient client;
    private MqttConnectOptions conOpt;

//        private String host = "tcp://10.0.2.2:61613";//模拟器
    private String host = "tcp://192.168.1.102:61613";//真机,实际是电脑端服务器部署的ip地址,不是手机的ip地址
    //对应MQTT\apache-apollo-1.7.1\bin\mybroker\etc\users.properties里面的admin=password,也可以自行修改,也对应网页管理的登录账号密码
    private String userName = "admin";
    private String passWord = "password";
    private static String myTopic = "topic";//订阅的topic
    private String clientId = "test1";//不同客户端需要修改值

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        init();
        return super.onStartCommand(intent, flags, startId);
    }

    public static void publish(String msg){
        String topic = myTopic;
        Integer qos = 0;
        Boolean retained = false;
        try {
            client.publish(topic, msg.getBytes(), qos.intValue(), retained.booleanValue());
        } catch (MqttException 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 = myTopic;
        Integer qos = 0;
        Boolean retained = false;
        if ((!message.equals("")) || (!topic.equals(""))) {
            // 最后的遗嘱
            try {
        //如果项目中需要知道客户端是否掉线可以调用该方法。设置最终端口的通知消息 
                conOpt.setWill(topic, message.getBytes(), qos.intValue(), retained.booleanValue());
            } catch (Exception e) {
                Log.i(TAG, "Exception Occured", e);
                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) {
            Log.i(TAG, "连接成功 ");
            try {
                // 订阅myTopic话题
                client.subscribe(myTopic,1);
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onFailure(IMqttToken arg0, Throwable arg1) {
            arg1.printStackTrace();
            // 连接失败,重连
        }
    };

    // MQTT监听并且接受消息
    private MqttCallback mqttCallback = new MqttCallback() {

        @Override
        public void messageArrived(String topic, MqttMessage message) throws Exception {

            String str1 = new String(message.getPayload());
            MQTTMessage msg = new MQTTMessage();
            msg.setMessage(str1);
            EventBus.getDefault().post(msg);
            String str2 = topic + ";qos:" + message.getQos() + ";retained:" + message.isRetained();
            Log.i(TAG, "messageArrived:" + str1);
            Log.i(TAG, str2);
        }

        @Override
        public void deliveryComplete(IMqttDeliveryToken arg0) {

        }

        @Override
        public void connectionLost(Throwable arg0) {
            // 失去连接,重连
        }
    };

    /** 判断网络是否连接 */
    private boolean isConnectIsNomarl() {
        ConnectivityManager connectivityManager = (ConnectivityManager) this.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = connectivityManager.getActiveNetworkInfo();
        if (info != null && info.isAvailable()) {
            String name = info.getTypeName();
            Log.i(TAG, "MQTT当前网络名称:" + name);
            return true;
        } else {
            Log.i(TAG, "MQTT 没有可用网络");
            return false;
        }
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}
=========
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

public class MainActivity extends AppCompatActivity {
    private TextView resultTv;

    String TAG = "MQTTService";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        EventBus.getDefault().register(this);
        Log.d(TAG, "oncreate");
        resultTv = (TextView) findViewById(R.id.tv_result);
        startService(new Intent(this, MQTTService.class));
        findViewById(R.id.publishBtn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.d(TAG, "click---------");
                MQTTService.publish("发布的消息内容");
            }
        });
    }
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void getMqttMessage(MQTTMessage mqttMessage){
        Log.i(MQTTService.TAG,"get message:"+mqttMessage.getMessage());
        Toast.makeText(this,mqttMessage.getMessage(),Toast.LENGTH_SHORT).show();
    }
    @Override
    protected void onDestroy() {
        EventBus.getDefault().unregister(this);
        super.onDestroy();
    }
}
========
public class MQTTMessage {
    String message;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

猜你喜欢

转载自blog.csdn.net/u010672559/article/details/81101070