Android适用于IOT场景的MQTT-Demo

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_24712507/article/details/86705842

MQTT:适用于IOT环境的轻量级网络框架。

原理:观察者模式,订阅/发布。

场景:阿里云IOT平台。

网络框架,本篇文章只关注Android端(终端)的使用。

参考官方文档:阿里云-微消息队列MQTT

消息发送是订阅推送的形式,终端与云端建立连接,并订阅主题,云端向终端推送消息。

优点是使用方便,资源利用小,支持断线重连和断线缓存,支持TCP也支持SSL连接。缺点的话就是坑比较多,一路坑坑洼洼。

截止目前,阿里云官网上关于Android的文档还没有,可参考java的demo,经测试一样用。文档也不太清晰,关于API基本就是看Demo。

具体说明及服务器端配置详看官方文档,服务器端代码也比较简单,和Android端类似,下面讲述Android端步骤:

1.gradle引入:

implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.0'
implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'
implementation group: 'commons-codec', name: 'commons-codec', version: '1.5'

其中,第一个是主包;第二个为了适配Android,带有广播服务之类的组件;第三个为了引入SHA1加密等。

2.权限比较良心,没有什么乱七八糟:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

3.声明服务:

<service android:name="org.eclipse.paho.android.service.MqttService" />

4.MqttAndroidClient,这里的回调建议设置成订阅消息的回调。以下代码建议放到服务中,start还是bind的方式看业务逻辑,但是记得要在服务destroy的时候断开连接。

mqttAndroidClient = new MqttAndroidClient(MyMqttService.this, NetConstant.BROKER, NetConstant.CLIENT_ID);
        mqttAndroidClient.setCallback(new MqttCallback() { //设置监听订阅消息的回调

            @Override
            public void connectionLost(Throwable cause) {
                //连接断开
                Log.d(TAG, "connectionLost: 连接丢失");
                cause.printStackTrace();
            }

            @Override
            public void messageArrived(String topic, MqttMessage message) {
                //订阅的消息送达,推送notify
                String payload = new String(message.getPayload());
                Log.d(TAG, "Topic: " + topic + " ==> Payload: " + payload);
            }

            @Override
            public void deliveryComplete(IMqttDeliveryToken token) {
                //即服务器成功delivery消息
                Log.d(TAG, "deliveryComplete: ");
            }
        });

5.设置连接参数,这块参数问后台要。clientId是识别到此设备的id,要和后台统一规则,并且后台设置是全部推送还是定向。在这里我们用签名鉴权方式,网上大部分都是用的token鉴权。签名鉴权阿里云的这个需要用到加密工具,都可以从阿里云的demo中拿到。

/**
         * 计算签名,将签名作为MQTT的password。
         * 签名的计算方法,参考工具类MacSignature,第一个参数是ClientID的前半部分,即GroupID
         * 第二个参数阿里云的SecretKey
         */
        String sign = "";
        try {
            sign = MacSignature.macSignature(NetConstant.CLIENT_ID, NetConstant.SECRET_KEY);
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        //新建连接设置
        MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
        //断开后,是否自动连接
        mqttConnectOptions.setAutomaticReconnect(true);
        //是否清空客户端的连接记录。若为true,则断开后,broker将自动清除该客户端连接信息
        mqttConnectOptions.setCleanSession(false);
        //设置超时时间,单位为秒
        //mqttConnectOptions.setConnectionTimeout(60);
        //心跳时间,单位为秒。即多长时间确认一次Client端是否在线
        mqttConnectOptions.setKeepAliveInterval(60);
        //允许同时发送几条消息(未收到broker确认信息)
        //mqttConnectOptions.setMaxInflight(10);
        //选择MQTT版本
        mqttConnectOptions.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1_1);

        mqttConnectOptions.setUserName("Signature|" + NetConstant.ACESS_KEY + "|" + NetConstant.INSTANCE_ID);
        mqttConnectOptions.setPassword(sign.toCharArray());
        mqttConnectOptions.setServerURIs(new String[]{NetConstant.BROKER});

6.连接并监听回调

try {
            //开始连接
            mqttAndroidClient.connect(mqttConnectOptions, null, new IMqttActionListener() {
                @Override
                public void onSuccess(IMqttToken asyncActionToken) {
                    Log.d(TAG, "onSuccess: Success to connect to 连接成功 " + NetConstant.BROKER);
                    DisconnectedBufferOptions disconnectedBufferOptions = new DisconnectedBufferOptions();
                    disconnectedBufferOptions.setBufferEnabled(true);
                    disconnectedBufferOptions.setBufferSize(100);
                    disconnectedBufferOptions.setPersistBuffer(false);
                    disconnectedBufferOptions.setDeleteOldestMessages(false);
                    mqttAndroidClient.setBufferOpts(disconnectedBufferOptions);
                    //成功连接以后开始订阅
                    subscribeAllTopics();
                }

                @Override
                public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                    //连接失败
                    Log.d(TAG, "onFailure: Failed to connect to 连接失败 " + NetConstant.BROKER);
                    exception.printStackTrace();
                }
            });
        } catch (MqttException ex) {
            ex.printStackTrace();
        }

7.订阅服务

    /**
     * 订阅消息
     */
    public void subscribeToTopic(String subscriptionTopic) {
        try {
            mqttAndroidClient.subscribe(subscriptionTopic, 0, null, new IMqttActionListener() {
                @Override
                public void onSuccess(IMqttToken asyncActionToken) {
                    Log.d(TAG, "onSuccess: Success to Subscribed!");
                }

                @Override
                public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                    Log.d(TAG, "onFailure: " + exception.getCause());
                    Log.d(TAG, "onFailure: Failed to subscribe " + exception.getMessage());
                    exception.printStackTrace();
                }
            });
        } catch (MqttException ex) {
            Log.d(TAG, "subscribeToTopic: Exception whilst subscribing");
            ex.printStackTrace();
        }
    }

8.发布消息

    /**
     * 发布消息
     */
    public void publishMessage(String msg) {
        try {
            MqttMessage message = new MqttMessage();
            message.setPayload(msg.getBytes());
//            参数topic:发布消息的主题
//            参数payload:消息的字节数组
//            参数qos:提供消息的服务质量,可传0、1或2
//            参数retained:是否在服务器保留断开连接后的最后一条消息
            mqttAndroidClient.publish(IOT_TOPIC, message);
            Log.d(TAG, "publishMessage: Message Published: " + msg);
        } catch (MqttException e) {
            Log.d(TAG, "publishMessage: Error Publishing: " + e.getMessage());
            e.printStackTrace();
        }
    }

整体代码可以从git上下载学习:MQTTDemo

关于Android-SDK使用的git:MQTT-SDK源码

猜你喜欢

转载自blog.csdn.net/qq_24712507/article/details/86705842