- 最新动态
- 功能总览
- 服务公告
- 计费说明
- 产品介绍
- 快速入门
- 用户指南
- 最佳实践
- 开发指南
-
API参考
- 应用侧API参考
- 设备侧MQTT/MQTTS接口参考
- 设备侧HTTPS接口参考
- 设备侧LwM2M接口参考
- 安全隧道WebSocket接口参考
- 模组AT指令参考
- 修订记录
- SDK参考
- 场景代码示例
-
常见问题
- 热门问题
-
方案咨询
- 连接IoT平台的业务场景有哪些?
- 设备管理服务和设备接入服务合一后的差异点是什么?
- IAM子用户或子项目是否可以开通物联网平台服务?
- 物联网平台支持在华为云的哪些区域开通?
- 华为是否提供模组/硬件终端/应用软件等?
- IAM用户访问API提示没有权限?(是否区分版本?)
- 创建规则或者设置资源文件存储时候提示赋予Security Administrator权限
- 物联网平台设置默认资源空间的规则是什么?
- 设备接入服务如何获取设备数据?
- 物联网平台的资源空间和设备可以无限创建吗?
- 物联网平台支持批量注册设备吗?
- 物联网平台对应用侧和设备侧在开发或使用时有限制吗?
- 物联网平台支持的DTLS加密算法有哪些?
- 物联网平台支持二进制大小端模式切换吗?
- 什么是NB-IoT?
- 物联网平台支持的硬件架构和使用的相关组件有哪些?
- 如何获取平台接入地址?
- 设备集成相关问题
- 设备侧SDK相关问题
- 设备发放相关问题
- LWM2M/CoAP接入相关问题
- MQTT接入相关问题
- 泛协议接入相关问题
- 物模型相关问题
- 消息通信相关问题
- 订阅推送相关问题
- 编解码插件相关问题
- OTA升级相关问题
- 应用集成相关问题
- 实例管理相关问题
- 视频帮助
- 文档下载
- 通用参考
链接复制成功!
Android Demo使用说明
概述
本文以Android语言为例,介绍通过MQTTS/MQTT协议接入平台,基于平台接口实现“属性上报”、“订阅接收命令”等功能。
前提条件
准备工作
- 安装android studio
访问android studio官网,选择合适系统的版本下载并安装。(本文以windows 64-bit系统Android Studio 3.5为例)。
- 安装JDK(也可以使用IDE自带的JDK)
- 访问Oracle官网,选择合适的JDK版本单击“Download”下载(本文以Windows x64 JDK8为例)。
- 下载完成后,运行安装文件,根据界面提示安装。
导入代码样例
- 下载quickStart(Android)样例。
- 运行Android Studio,单击Open,选择步骤1中下载的样例。
- 完成代码导入。
代码目录简述:
- manifests:Android项目的配置文件;
- java:项目java代码;
MainActivity:demo界面类;
ConnectUtils:mqtt连接辅助类;
- asset:项目原生文件;
DigiCertGlobalRootCA.bks:设备校验平台身份的证书,用于设备侧接入物联网平台登录鉴权使用;
- res:项目资源文件(图片、布局、字符串等);
- gradle:项目全局的gradle构建脚本.
- libs:项目中使用到了第三方jar包归档目录
org.eclipse.paho.android.service-1.1.0.jar:Android启动后台service组件实现消息发布和订阅的组件;
org.eclipse.paho.client.mqttv3-1.2.0.jar:mqtt java客户端组件;
- (可选)了解Demo里的关键工程配置(默认不用修改)。
- AndroidManifest.xml:需要添加,支持mqtt service。
<service android:name="org.eclipse.paho.android.service.MqttService" />
- build.gradle:添加依赖,导入libs下的两个mqtt连接所需要的jar包。(也可以添加jar包官网引用)
implementation files('libs/org.eclipse.paho.android.service-1.1.0.jar') implementation files('libs/org.eclipse.paho.client.mqttv3-1.2.0.jar')
- AndroidManifest.xml:需要添加,支持mqtt service。
界面展示
- MainActivity类主要提供了界面显示,请填写设备ID和设备密钥,在物联网平台或调用接口注册设备后获取。
- 示例中默认写了设备侧接入的域名地址(SSL加密接入时该域名要与对应的证书文件匹配使用)。
private final static String IOT_PLATFORM_URL = "iot-mqtts.cn-north-4.myhuaweicloud.com";
- 用户可以选择设备侧建链时是否SSL加密/不加密,选择Qos方式是0还是1,当前不支持Qos2,可参考使用限制。
checkbox_mqtt_connet_ssl.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked) { isSSL = true; checkbox_mqtt_connet_ssl.setText("SSL加密"); } else { isSSL = false; checkbox_mqtt_connet_ssl.setText("SSL不加密"); } } })
建立连接
设备或网关在接入物联网平台时首先需要和平台建立连接,从而将设备或网关与平台进行关联。开发者通过传入设备信息,将设备或网关连接到物联网平台。
- MainActivity类主要提供建立MQTT/MQTTS连接等方法,MQTT默认使用1883端口,MQTTS默认使用8883端口(需要加载证书)。
if (isSSL) { editText_mqtt_log.append("开始建立MQTTS连接" + "\n"); serverUrl = "ssl://" + IOT_PLATFORM_URL + ":8883"; } else { editText_mqtt_log.append("开始建立MQTT连接" + "\n"); serverUrl = "tcp://" + IOT_PLATFORM_URL + ":1883"; }
- ConnectUtils类主要提供了SSL加载证书的getMqttsCerificate方法,如果是MQTTS建链方式,需要调用该方法加载证书。
DigiCertGlobalRootCA.bks:设备校验平台身份的证书,用于设备侧接入物联网平台登录鉴权使用,可以在资源获取中下载证书文件。
SSLContext sslContext = SSLContext.getInstance("SSL"); KeyStore keyStore = KeyStore.getInstance("bks"); keyStore.load(context.getAssets().open("DigiCertGlobalRootCA.bks"), null);//加载libs目录下的证书 TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509"); trustManagerFactory.init(keyStore); TrustManager[] trustManagers = trustManagerFactory.getTrustManagers(); sslContext.init(null, trustManagers, new SecureRandom()); sslSocketFactory = sslContext.getSocketFactory();
- MainActivity类提供了设置初始化MqttConnectOptions的方法。mqtt连接心跳时间的建议值是120秒,有使用限制。
mqttAndroidClient = new MqttAndroidClient(mContext, serverUrl, clientId); private MqttConnectOptions intitMqttConnectOptions(String currentDate) { String password = ConnectUtils.sha256_HMAC(editText_mqtt_device_connect_password.getText().toString(), currentDate); MqttConnectOptions mqttConnectOptions = new MqttConnectOptions(); mqttConnectOptions.setAutomaticReconnect(true); mqttConnectOptions.setCleanSession(true); mqttConnectOptions.setKeepAliveInterval(120); mqttConnectOptions.setConnectionTimeout(30); mqttConnectOptions.setUserName(editText_mqtt_device_connect_deviceId.getText().toString()); mqttConnectOptions.setPassword(password.toCharArray()); return mqttConnectOptions; }
- MainActivity类提供了Mqtt客户端建立连接的的方法connect,并通过回调函数处理连接后的消息返回结果。
mqttAndroidClient.connect(mqttConnectOptions, null, new IMqttActionListener()
mqttAndroidClient.setCallback(new MqttCallBack4IoTHub());
注:如果连接失败,在initMqttConnects函数中的onFailure回调函数中已实现退避重连,代码样例如下:
@Override public void onFailure(IMqttToken asyncActionToken, Throwable exception) { exception.printStackTrace(); Log.e(TAG, "Fail to connect to: " + exception.getMessage()); editText_mqtt_log.append("建立连接失败:" + exception.getMessage() + "\n"); //退避重连 int lowBound = (int) (defaultBackoff * 0.8); int highBound = (int) (defaultBackoff * 1.2); long randomBackOff = random.nextInt(highBound - lowBound); long backOffWithJitter = (int) (Math.pow(2.0, (double) retryTimes)) * (randomBackOff + lowBound); long waitTImeUntilNextRetry = (int) (minBackoff + backOffWithJitter) > maxBackoff ? maxBackoff : (minBackoff + backOffWithJitter); try { Thread.sleep(waitTImeUntilNextRetry); } catch (InterruptedException e) { System.out.println("sleep failed, the reason is" + e.getMessage().toString()); } retryTimes++; MainActivity.this.initMqttConnects(); }
订阅Topic
订阅某Topic的设备才能接收broker发布的关于该Topic的消息,关于平台预置Topic可参考Topic定义。
在MainActivity类中提供了订阅命令下发Topic、订阅Topic、取消订阅Topic等功能:
String mqtt_sub_topic_command_json = String.format("$oc/devices/%s/sys/commands/#", editText_mqtt_device_connect_deviceId.getText().toString());
mqttAndroidClient.subscribe(getSubscriptionTopic(), qos, null, new IMqttActionListener()
mqttAndroidClient.unsubscribe(getSubscriptionTopic(), null, new IMqttActionListener()
如果建链成功,可以在回调函数中订阅Topic:
mqttAndroidClient.connect(mqttConnectOptions, null, new IMqttActionListener() { @Overridepublic void onSuccess(IMqttToken asyncActionToken) { ...... subscribeToTopic(); }
建链成功后,APP界面日志栏显示如下信息:
属性上报
属性上报是指设备主动向平台上报自己的属性。更多接口信息请参考设备属性上报。
在MainActivity类中实现了属性上报Topic、属性上报功能。
String mqtt_report_topic_json = String.format("$oc/devices/%s/sys/properties/report", editText_mqtt_device_connect_deviceId.getText().toString());
MqttMessage mqttMessage = new MqttMessage(); mqttMessage.setPayload(publishMessage.getBytes()); mqttAndroidClient.publish(publishTopic, mqttMessage);
设备上报属性成功后可在设备详情页面查看到上报的属性


如果在“设备详情”页面没有最新上报数据,请确认设备上报的服务/属性和产品模型中的服务/属性一致。
接收下发命令
在MainActivity类中提供了接收平台下发命令的功能,在MQTT建链完成后,可以在管理控制台设备详情中命令下发或使用应用侧Demo对该设备ID进行命令下发,例如下发参数名为command,参数值为5的命令,下发成功后,在MQTT的回调函数中接收到。
private final class MqttCallBack4IoTHub implements MqttCallbackExtended { ...... @Overridepublic void messageArrived(String topic, MqttMessage message) throws Exception { Log.i(TAG, "Incoming message: " + new String(message.getPayload(), StandardCharsets.UTF_8)); editText_mqtt_log.append("MQTT接收下发命令成功:" + message + "\n"); }
在设备详情页面可以查看到命令下发状态,这里显示timeout是因为该Demo示例中仅演示接收命令,没有回复响应给平台。
属性上报和命令接收成功,APP界面显示如下: