跟我做,让Android封装MQTT连接阿里云平台!开源

Posted kasami_

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了跟我做,让Android封装MQTT连接阿里云平台!开源相关的知识,希望对你有一定的参考价值。

《每谈及物联网都难以离开的MQTT协议!》中,我们使用了模拟的方式让MQTT接入阿里云云服务器。但是我们实际中使用时却不能模拟,每一步都得自己调,毫无疑问会非常的麻烦。那么我们必须把这些指令和操作写在程序中,让其自动、智能地运行。

以下是我们将MQTT协议和连接阿里云平台的操作通过android studio写入app中,并简单设计UI。实现手机app远程控制单片机LED灯亮灭的功能。

app源码:https://github.com/Liangyz2019/IoT-LED-APP-

首先,我们得引入mqtt.jar

选取org.eclipse.paho.client.mqttv3/1.2.2/org.eclipse.paho.client.mqttv3-1.2.2.jar下载

jar包拷贝到新工程的app/libs目录并导入

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
AndroidManifest添加网络权限

</application>
    <uses-permission android:name="android.permission.INTERNET" />
</manifest>

MainActivity添加包

package com.example.test;

import androidx.appcompat.app.AppCompatActivity;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.TextView;


import com.example.test.AliyunIoTSignUtil;

import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;

import java.io.IOException;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

在public class MainActivity extends AppCompatActivity {}中
初始定义一些基本信息

 private static final String TAG =MainActivity.class.getSimpleName();

    private TextView msgTextView;

    private String productKey="a16OKk6dTya";
    private String deviceName="KAMI";
    private String deviceSecret="8790bd0545dd874d77fcac85729fc4bf";

    private final String payloadJson1="{\\"ParkingState\\":1}";
    private final String payloadJson2="{\\"ParkingState\\":0}";
    private MqttClient mqttClient=null;

    final int POST_DEVICE_PROPERTIES_SUCCESS = 1002;
    final int POST_DEVICE_PROPERTIES_ERROR = 1003;

    private String responseBody = "";


    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case POST_DEVICE_PROPERTIES_SUCCESS:
                    showToast("发送数据成功");
                    break;
                case POST_DEVICE_PROPERTIES_ERROR:
                    showToast("post数据失败");
                    break;
            }
        }
    };

开始APP生命周期

  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
         msgTextView = findViewById(R.id.msgTextView);

        findViewById(R.id.activate_button).setOnClickListener((l) -> {
            new Thread(() -> initAliyunIoTClient()).start();
        });

        findViewById(R.id.post_button1).setOnClickListener((l) -> {
            mHandler.postDelayed(() -> postDeviceProperties1(), 1000);
        });

        findViewById(R.id.post_button2).setOnClickListener((l) -> {
            mHandler.postDelayed(() -> postDeviceProperties2(), 1000);
        });
     }

连接阿里云物联网平台

 private void initAliyunIoTClient() {

        try {
            String clientId = "12345"+ System.currentTimeMillis();

            Map<String, String> params = new HashMap<String, String>(16);
            params.put("productKey", productKey);
            params.put("deviceName", deviceName);
            params.put("clientId", clientId);
            String timestamp = String.valueOf(System.currentTimeMillis());
            params.put("timestamp", timestamp);

            // cn-shanghai
            String targetServer ="tcp://"+ productKey + ".iot-as-mqtt.cn-shanghai.aliyuncs.com:1883";

            String mqttclientId = clientId + "|securemode=3,signmethod=hmacsha1,timestamp=" + timestamp + "|";
            String mqttUsername = deviceName + "&" + productKey;
            String mqttPassword = AliyunIoTSignUtil.sign(params, deviceSecret, "hmacsha1");

            connectMqtt(targetServer, mqttclientId, mqttUsername, mqttPassword);


        } catch (Exception e) {
            e.printStackTrace();
            responseBody = e.getMessage();
            mHandler.sendEmptyMessage(POST_DEVICE_PROPERTIES_ERROR);
        }
    }

登陆MQTT

 public void connectMqtt(String url, String clientId, String mqttUsername, String mqttPassword) throws Exception {

        MemoryPersistence persistence = new MemoryPersistence();
        mqttClient = new MqttClient(url, clientId, persistence);
        MqttConnectOptions connOpts = new MqttConnectOptions();
        // MQTT 3.1.1
        connOpts.setMqttVersion(4);
        connOpts.setAutomaticReconnect(true);
        connOpts.setCleanSession(true);

        connOpts.setUserName(mqttUsername);
        connOpts.setPassword(mqttPassword.toCharArray());
        connOpts.setKeepAliveInterval(60);

        mqttClient.connect(connOpts);
        Log.d(TAG, "connected " + url);

    }

发布主题Publish

    private void postDeviceProperties1() {

        try {

            Random random = new Random();

            //上报数据
            String payload = String.format(payloadJson1, String.valueOf(System.currentTimeMillis()), 10 + random.nextInt(20), 50 + random.nextInt(50));
            responseBody = payload;
            MqttMessage message = new MqttMessage(payload.getBytes("utf-8"));
            message.setQos(1);


            String pubTopic = "/" + productKey + "/" + deviceName + "/user/update";
            mqttClient.publish(pubTopic, message);
            Log.d(TAG, "publish topic=" + pubTopic + ",payload=" + payload);
            mHandler.sendEmptyMessage(POST_DEVICE_PROPERTIES_SUCCESS);

            mHandler.postDelayed(() -> postDeviceProperties1(), 5 * 1000);
        } catch (Exception e) {
            e.printStackTrace();
            responseBody = e.getMessage();
            mHandler.sendEmptyMessage(POST_DEVICE_PROPERTIES_ERROR);
            Log.e(TAG, "postDeviceProperties error " + e.getMessage(), e);
        }
    }

    private void postDeviceProperties2() {

        try {

            Random random = new Random();

            //上报数据
            String payload = String.format(payloadJson2, String.valueOf(System.currentTimeMillis()), 10 + random.nextInt(20), 50 + random.nextInt(50));
            responseBody = payload;
            MqttMessage message = new MqttMessage(payload.getBytes("utf-8"));
            message.setQos(1);


            String pubTopic = "/" + productKey + "/" + deviceName + "/user/update";
            mqttClient.publish(pubTopic, message);
            Log.d(TAG, "publish topic=" + pubTopic + ",payload=" + payload);
            mHandler.sendEmptyMessage(POST_DEVICE_PROPERTIES_SUCCESS);

            mHandler.postDelayed(() -> postDeviceProperties2(), 5 * 1000);
        } catch (Exception e) {
            e.printStackTrace();
            responseBody = e.getMessage();
            mHandler.sendEmptyMessage(POST_DEVICE_PROPERTIES_ERROR);
            Log.e(TAG, "postDeviceProperties error " + e.getMessage(), e);
        }
    }
    private void showToast(String msg) {
        msgTextView.setText(msg + "\\n" + responseBody);
    }

}

解码获取password,在《物联网却不能物物相联?阿里云物联网平台得这么设置!》里面如果得到了password,不用这个class也行

package com.example.test;

import java.util.Arrays;
import java.util.Map;

import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

public class AliyunIoTSignUtil {

    public static String sign(Map<String, String> params, String deviceSecret, String signMethod) {
        //将参数Key按字典顺序排序
        String[] sortedKeys = params.keySet().toArray(new String[] {});
        Arrays.sort(sortedKeys);

        //生成规范化请求字符串
        StringBuilder canonicalizedQueryString = new StringBuilder();
        for (String key : sortedKeys) {
            if ("sign".equalsIgnoreCase(key)) {
                continue;
            }
            canonicalizedQueryString.append(key).append(params.get(key));
        }

        try {
            String key = deviceSecret;
            return encryptHMAC(signMethod,canonicalizedQueryString.toString(), key);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * HMACSHA1加密
     *
     */
    public static String encryptHMAC(String signMethod, String content, String key) throws Exception {
        SecretKey secretKey = new SecretKeySpec(key.getBytes("utf-8"), signMethod);
        Mac mac = Mac.getInstance(secretKey.getAlgorithm());
        mac.init(secretKey);
        byte[] data = mac.doFinal(content.getBytes("utf-8"));
        return bytesToHexString(data);
    }

    public static final String bytesToHexString(byte[] bArray) {

        StringBuffer sb = new StringBuffer(bArray.length);
        String sTemp;
        for (int i = 0; i < bArray.length; i++) {
            sTemp = Integer.toHexString(0xFF & bArray[i]);
            if (sTemp.length() < 2) {
                sb.append(0);
            }
            sb.append(sTemp.toUpperCase());
        }
        return sb.toString();
    }

}

简单UI设计

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/msgTextView"
        android:layout_width="62dp"
        android:layout_height="563dp"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:padding="10dp"
        android:text="就你也会点灯?"
        android:textColor="#E91E63"
        android:textSize="36sp"
        android:textStyle="bold"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.536"
        app:layout_constraintStart_toStartOf="parent"
        tools:layout_editor_absoluteY="128dp" />

    <Button
        android:id="@+id/activate_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:layout_marginTop="7dp"
        android:layout_marginEnd="232dp"
        android:layout_marginRight="232dp"
        android:padding="10dp"
        android:text="激活"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        tools:layout_editor_absoluteY="274dp" />

    <Button
        android:id="@+id/post_button1&

以上是关于跟我做,让Android封装MQTT连接阿里云平台!开源的主要内容,如果未能解决你的问题,请参考以下文章

使用MQTT连接阿里云的物联网云平台

使用MQTT连接阿里云的物联网云平台

ESP32基础应用之使用mqtt连接阿里云物联网平台

MQTT网关连接阿里云平台案例教程

中移M5311模块MQTT协议连接阿里云物联网平台(干货)

阿里云物联网平台配置ESP8266真实设备AT串口连接,支持MQTT协议通信