【Android+物联网】Android封装MQTT连接阿里云物联网平台

前言:

亲测可行,本文实现Android封装MQTT连接阿里云物联网平台。将MQTT协议和连接阿里云平台的操作通过Android studio写入APP中,并简单设计UI。实现手机APP远程控制单片机LED灯亮灭的功能。

关于《Android软件开发》,见如下专栏

https://blog.csdn.net/m0_61712829/category_12455686.html?spm=1001.2014.3001.5482

关于《完整实现STM32+ESP8266+MQTT+阿里云+APP》,见如下专栏

https://blog.csdn.net/m0_61712829/category_12545281.html?spm=1001.2014.3001.5482

源码可于上方资源绑定栏下载。

1.下载mqtt.jar包

下载链接:Index of /repositories/paho-releases/org/eclipse/paho

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

进入链接后,过程如下:

首先,选取 org.eclipse.paho.client.mqttv3/

​选择 1.2.1/

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

下载成功如下

然后,将下载成功的jar包拷贝到你工程的app/libs目录

2.导入mqtt.jar包

点击项目页面最右边的设置按钮,选择 Project Structure..

进入后,按如下图顺序点击选择

在step1. 处输入路径 libs\org.eclipse.paho.client.mqttv3-1.2.2.jar

导入mqtt.jar包成功,点击ok

​ 3.程序说明

1.在 AndroidManifest.xml 添加网络权限

复制代码
</application>
    <uses-permission android:name="android.permission.INTERNET" />
</manifest>

位置如下所示:

​ 2.在 MainActivity.java 添加包

MainActivity.java 在如下位置

注意:将代码中涉及的工程名改为你的工程名

复制代码
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;

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

注意:将productKey、deviceName、deviceSecret 改为你自己的;将json数据格式中的标识符改为你自己的

复制代码
 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;
            }
        }
    };

4.在MainActivity.java中,写开始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);
        });
     }

5.在MainActivity.java中,写连接阿里云物联网平台函数

复制代码
 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);
        }
    }

6.在MainActivity.java中,写登陆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);

    }

7.在MainActivity.java中,写发布主题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);
    }

}

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

在如下位置添加 AliyunIoTSignUtil.java

AliyunIoTSignUtil.java中的代码如下

复制代码
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();
    }

}
  1. 简单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:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_alignParentStart="true"
         android:layout_alignParentLeft="true"
         android:layout_alignParentTop="true"
         android:layout_marginStart="205dp"
         android:layout_marginLeft="205dp"
         android:layout_marginTop="6dp"
         android:layout_marginBottom="10dp"
         android:padding="10dp"
         android:text="点灯"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintHorizontal_bias="0.498"
         app:layout_constraintStart_toStartOf="parent"
         tools:layout_editor_absoluteY="351dp" />
    
     <Button
         android:id="@+id/post_button2"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_alignParentTop="true"
         android:layout_alignParentEnd="true"
         android:layout_marginTop="6dp"
         android:layout_marginEnd="10dp"
         android:text="灭灯" />

参考链接:跟我做,让Android封装MQTT连接阿里云平台!【开源】_跟我做,让安卓封装mqtt-CSDN博客

本文参考的APP源码:GitCode - 开发者的代码家园

相关推荐
兮动人1 小时前
Eureka注册中心通用写法和配置
java·云原生·eureka
爱编程的小白L3 小时前
基于springboot志愿服务管理系统设计与实现(附源码)
java·spring boot·后端
聪明的笨猪猪5 小时前
Java Redis “持久化”面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
聪明的笨猪猪5 小时前
Java Redis “核心基础”面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
奋斗的小monkey7 小时前
Spring Boot 3.x核心特性与性能优化实战
java·spring boot·微服务·性能优化·响应式编程
程序猿DD8 小时前
将 GPU 级性能带到企业级 Java:CUDA 集成实用指南
java·架构
想躺平的咸鱼干8 小时前
远程MCP的调用和阿里云生态的知识库和工作流的使用
阿里云·大模型·云计算·idea·格式化输出·mcp
一成码农9 小时前
JavaSE面向对象(上)
java
qq_574656259 小时前
java-代码随想录第66天|Floyd 算法、A * 算法精讲 (A star算法)
java·算法·leetcode·图论