android使用mqtt连接阿里云物联网平台

我的个人网站 http://www.cheese.ren/

博客来源 http://www.cheese.ren/blog/blog/334

欢迎交换友链 :-)


最近查看了一下阿里云物联网平台的文档,发现使用mqtt的连接方法并没有写的很清楚,就来稍微归纳一下


相关网站

MQTT:https://mqtt.org/ (物联网消息传递标准)

Eventbus:https://github.com/greenrobot/EventBus (Android和Java的发布/订阅事件总线)


在build.gradle中添加下列依赖

//MQTT
implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.0'
implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'
//Eventbus
implementation 'org.greenrobot:eventbus:3.0.0'
implementation 'org.greenrobot:eventbus:3.1.1'

重新Make Project一下即可


创建IoT.java

package com.example.fackunlocking;

import android.content.Context;

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

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

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

public class IoT {
    private String productKey, deviceName, deviceSecret, regionId, topic; //基础配置

    private MqttClient mqttClient;


    public IoT(String productKey, String deviceName, String deviceSecret, String regionId) {
        this.productKey = productKey;
        this.deviceName = deviceName;
        this.deviceSecret = deviceSecret;
        this.regionId = regionId; //这里设置的是物联网平台的区域,例如“华东2(上海)”的值为“cn-shanghai”,具体地区对应的值请查看阿里云的文档
        topic = "/" + productKey + "/" + deviceName;
    }


    //连接
    public boolean connect() {
        try {
            //配置 服务器地址 客户端id 用户名 密码
            String clientId = "java" + System.currentTimeMillis();
            String timestamp = String.valueOf(System.currentTimeMillis());
            Map<String, String> params = new HashMap<>(16);
            params.put("productKey", productKey);
            params.put("deviceName", deviceName);
            params.put("clientId", clientId);
            params.put("timestamp", timestamp);
            String targetServer = "tcp://" + productKey + ".iot-as-mqtt." + regionId + ".aliyuncs.com:1883";
            String mqttClientId = clientId + "|securemode=3,signmethod=hmacsha1,timestamp=" + timestamp + "|";
            String mqttUsername = deviceName + "&" + productKey;
            String mqttPassword = sign(params, deviceSecret, "hmacsha1"); //获取密码
            //使用MQTT进行连接
            MemoryPersistence persistence = new MemoryPersistence();
            mqttClient = new MqttClient(targetServer, mqttClientId, persistence);
            MqttConnectOptions connectOptions = new MqttConnectOptions();
            connectOptions.setMqttVersion(4);
            connectOptions.setCleanSession(false);
            connectOptions.setAutomaticReconnect(false);
            connectOptions.setUserName(mqttUsername);
            connectOptions.setPassword(mqttPassword.toCharArray());
            connectOptions.setKeepAliveInterval(60);
            mqttClient.connect(connectOptions);
        }
        catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }


    //发布 topic是要发布的topic地址,只需补全剩下的地址即可 payload或许有一定的格式,可以在类中定义格式,本例子偷懒不写了=W=
    public boolean publish(String topic, String payload) {
        try {
            MqttMessage message = new MqttMessage(payload.getBytes("utf-8"));
            /*
                这里出现了Qos,稍微科普一下,后面就不再重复了
                参数0代表Sender发送的一条消息,Receiver最多能收到一次,也就是说Sender尽力向Receiver发送消息,如果发送失败,也就算了
                参数1代表Sender发送的一条消息,Receiver至少能收到一次,也就是说Sender向Receiver发送消息,如果发送失败,会继续重试,直到Receiver收到消息为止,但是因为重传的原因,Receiver有可能会收到重复的消息
                参数2代表Sender发送的一条消息,Receiver确保能收到而且只收到一次,也就是说Sender尽力向Receiver发送消息,如果发送失败,会继续重试,直到Receiver收到消息为止,同时保证Receiver不会因为消息重传而收到重复的消息
            */
            message.setQos(1);
            mqttClient.publish(topic, message);
        }
        catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }


    //订阅
    public boolean listen(Context context, String topic) {
        try {
            //注册广播
            EventBus.getDefault().register(this.connect());
            mqttClient.setCallback(new MqttCallback() {
                @Override
                public void connectionLost(Throwable cause) {

                }

                @Override
                public void messageArrived(String topic, MqttMessage message) throws Exception {
                    String str = new String(message.getPayload());
                    EventBus.getDefault().post(new MessageEvent(str));
                }

                @Override
                public void deliveryComplete(IMqttDeliveryToken token) {

                }
            });
            MqttTopic mqttTopic = mqttClient.getTopic(topic);
            mqttClient.subscribe(topic, 1);
        }
        catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }


    //关闭连接
    public boolean close(Context context) {
        try {
            EventBus.getDefault().unregister(context);//注销广播
            mqttClient.disconnect();
        }
        catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }


    private String sign(Map<String, String> params, String deviceSecret, String signMethod) {
        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);
        }
    }

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

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

}

发布消息的步骤

IoT iot = new IoT("productKey", "deviceName", "deviceSecret", "regionId")
iot.connect();

iot.publish("topic", "payload");

//用完请关掉!养成良好习惯!
//iot.close(Activity.this);

订阅消息的步骤

IoT iot = new IoT("productKey", "deviceName", "deviceSecret", "regionId")
iot.connect();

//订阅的方法
@RequiresApi(api = Build.VERSION_CODES.M)
@Subscribe(threadMode = ThreadMode.MAIN)
public void listenWay(MessageEvent messageEvent) {
    System.out.println(messageEvent.getMessage());
}

iot.listen(Activity.this, "topic");

//用完请关掉!养成良好习惯!
//iot.close(Activity.this);

当消息赶来时就会调用listenWay这个方法,很方便!


这样一个连接阿里云物联网平台的类就封装完成啦!或许有些地方不太准确,但大致意思是没错了的,更多的使用方法可以自行探索。

热门文章

暂无图片
编程学习 ·

exe4j详细使用教程(附下载安装链接)

一、exe4j介绍 ​ exe4j是一个帮助你集成Java应用程序到Windows操作环境的java可执行文件生成工具&#xff0c;无论这些应用是用于服务器&#xff0c;还是图形用户界面&#xff08;GUI&#xff09;或命令行的应用程序。如果你想在任务管理器中及Windows XP分组的用户友好任务栏…
暂无图片
编程学习 ·

AUTOSAR从入门到精通100讲(126)-浅谈车载充电系统通信方案

01 引言 本文深入研究车载充电系统策略,设计出一套基于电动汽车电池管理系统与车载充电机的CAN通信协议,可供电动汽车设计人员参考借鉴。 02 电动汽车充电系统通讯网络 电动汽车整车控制系统中采用的是CAN总线通信方式,由一个整车内部高速CAN网络、内部低速CAN网络和一个充电…
暂无图片
编程学习 ·

CMake(九):生成器表达式

当运行CMake时&#xff0c;开发人员倾向于认为它是一个简单的步骤&#xff0c;需要读取项目的CMakeLists.txt文件&#xff0c;并生成相关的特定于生成器的项目文件集(例如Visual Studio解决方案和项目文件&#xff0c;Xcode项目&#xff0c;Unix Makefiles或Ninja输入文件)。然…
暂无图片
编程学习 ·

47.第十章 网络协议和管理配置 -- 网络配置(八)

4.3.3 route 命令 路由表管理命令 路由表主要构成: Destination: 目标网络ID,表示可以到达的目标网络ID,0.0.0.0/0 表示所有未知网络,又称为默认路由,优先级最低Genmask:目标网络对应的netmaskIface: 到达对应网络,应该从当前主机哪个网卡发送出来Gateway: 到达非直连的网络,…
暂无图片
编程学习 ·

元宇宙技术基础

请看图&#xff1a; 1、通过AR、VR等交互技术提升游戏的沉浸感 回顾游戏的发展历程&#xff0c;沉浸感的提升一直是技术突破的主要方向。从《愤怒的小鸟》到CSGO,游戏建模方式从2D到3D的提升使游戏中的物体呈现立体感。玩家在游戏中可以只有切换视角&#xff0c;进而提升沉浸…
暂无图片
编程学习 ·

flink的伪分布式搭建

一 flink的伪分布式搭建 1.1 执行架构图 1.Flink程序需要提交给 Job Client2.Job Client将作业提交给 Job Manager3.Job Manager负责协调资源分配和作业执行。 资源分配完成后&#xff0c;任务将提交给相应的 Task Manage。4.Task Manager启动一个线程以开始执行。Task Manage…
暂无图片
编程学习 ·

十进制正整数与二进制字符串的转换(C++)

Function one&#xff1a; //十进制数字转成二进制字符串 string Binary(int x) {string s "";while(x){if(x % 2 0) s 0 s;else s 1 s;x / 2;}return s; } Function two&#xff1a; //二进制字符串变为十进制数字 int Decimal(string s) {int num 0, …
暂无图片
编程学习 ·

[含lw+源码等]微信小程序校园辩论管理平台+后台管理系统[包运行成功]Java毕业设计计算机毕设

项目功能简介: 《微信小程序校园辩论管理平台后台管理系统》该项目含有源码、论文等资料、配套开发软件、软件安装教程、项目发布教程等 本系统包含微信小程序做的辩论管理前台和Java做的后台管理系统&#xff1a; 微信小程序——辩论管理前台涉及技术&#xff1a;WXML 和 WXS…
暂无图片
编程学习 ·

树莓派驱动DHT11温湿度传感器

1&#xff0c;直接使用python库 代码如下 import RPi.GPIO as GPIO import dht11 import time import datetimeGPIO.setwarnings(True) GPIO.setmode(GPIO.BCM)instance dht11.DHT11(pin14)try:while True:result instance.read()if result.is_valid():print(ok)print(&quo…
暂无图片
编程学习 ·

ELK简介

ELK简介 ELK是三个开源软件的缩写&#xff0c;Elasticsearch、Logstash、Kibana。它们都是开源软件。不过现在还新增了一个 Beats&#xff0c;它是一个轻量级的日志收集处理工具(Agent)&#xff0c;Beats 占用资源少&#xff0c;适合于在各个服务器上搜集日志后传输给 Logstas…
暂无图片
编程学习 ·

Linux 基础

通常大数据框架都部署在 Linux 服务器上&#xff0c;所以需要具备一定的 Linux 知识。Linux 书籍当中比较著名的是 《鸟哥私房菜》系列&#xff0c;这个系列很全面也很经典。但如果你希望能够快速地入门&#xff0c;这里推荐《Linux 就该这么学》&#xff0c;其网站上有免费的电…
暂无图片
编程学习 ·

Windows2022 无线网卡装不上驱动

想来 Windows2022 和 windows10/11 的驱动应该差不多通用的&#xff0c;但是死活装不上呢&#xff1f; 搜一下&#xff0c;有人提到 “默认安装时‘无线LAN服务’是关闭的&#xff0c;如果需要开启&#xff0c;只需要在“添加角色和功能”中&#xff0c;选择开启“无线LAN服务…
暂无图片
编程学习 ·

【嵌入式面试宝典】版本控制工具Git常用命令总结

目录 创建仓库 查看信息 版本回退 版本检出 远程库 Git 创建仓库 git initgit add <file> 可反复多次使用&#xff0c;添加多个文件git commit -m <message> 查看信息 git status 仓库当前的状态git diff 差异对比git log 历史记录&#xff0c;提交日志--pret…
暂无图片
编程学习 ·

用Postman生成测试报告

newman newman是一款基于nodejs开发的可以运行postman脚本的工具&#xff0c;使用Newman&#xff0c;可以直接从命令运行和测试postman集合。 安装nodejs 下载地址&#xff1a;https://nodejs.org/en/download/ 选择自己系统相对应的版本内容进行下载&#xff0c;然后傻瓜式安…
暂无图片
编程学习 ·

Java面向对象之多态、向上转型和向下转型

文章目录前言一、多态二、引用类型之间的转换Ⅰ.向上转型Ⅱ.向下转型总结前言 今天继续Java面向对象的学习&#xff0c;学习面向对象的第三大特征&#xff1a;多态&#xff0c;了解多态的意义&#xff0c;以及两种引用类型之间的转换&#xff1a;向上转型、向下转型。  希望能…