本文介绍如何使用Paho Android Service接入阿里云物联网平台,并进行数据收发。

前提条件

已在物联网平台中,创建了产品和设备。

请参见创建产品单个创建设备

背景信息

Paho Android Service是一个基于Java语言的Paho MQTT库开发的MQTT客户端服务包。

准备开发环境

本示例使用的Android Studio版本为3.5.1,gradle版本为3.5.1。

请访问Android Studio官网下载Android Studio。Android开发相关教程,请查看Android Studio官方文档。

安装Paho Android Client

  1. 创建一个新的Android工程。
  2. 在gradle文件中,添加Paho Android Client依赖。本示例使用1.1.1版本的PahoAndroidClient,需添加以下依赖。
    • 在工程build.gradle中,添加Paho仓库地址。本示例使用release仓库。
      repositories {
          maven {
              url "https://repo.eclipse.org/content/repositories/paho-releases/"
          }
      }
    • 在应用build.gradle中,添加Paho Android Service。本示例中,使用1.1.1 release版本的Paho服务;底层基于paho.client.mqttv3-1.1.0版本,需添加以下依赖。
      dependencies {
          implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.0'
          implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'
      }
  3. 为了使App能够绑定到Paho Android Service,需要在AndroidManifest.xml中添加以下信息。
    • 声明以下服务。
      <!-- Mqtt Service -->
      <service android:name="org.eclipse.paho.android.service.MqttService">
      </service>
    • 添加Paho MQTT Service所需的权限。
      <uses-permission android:name="android.permission.WAKE_LOCK" />
      <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
      <uses-permission android:name="android.permission.INTERNET" />
      <uses-permission android:name="android.permission.READ_PHONE_STATE" />

接入物联网平台

  1. 单击AiotMqttOption.java,然后下载阿里云提供的计算MQTT连接参数所需的源码。

    AiotMqttOption.java文件中定义了AiotMqttOption()类。

    • 原型
      class AiotMqttOption
    • 功能

      用于计算设备接入物联网平台的MQTT连接参数usernamepasswordclientid

    • 成员
      类型定义 方法描述
      public AiotMqttOption getMqttOption(String productKey, String deviceName, String deviceSecret)

      根据设备的productKeydeviceNamedeviceSecret计算出MQTT连接参数usernamepasswordclientid

      public String getUsername()

      用于获取MQTT建连参数username

      public String getPassword()

      用于获取MQTT建连参数password

      public String getClientid()

      用于获取MQTT建连参数clientid

  2. AiotMqttOption.java导入Android项目。
  3. 在Android项目中,添加实现设备接入物联网平台的程序文件。

    您需编写程序调用AiotMqttOption.java中的AiotMqttOption()类计算MQTT连接参数,实现接入物联网平台和通信。

    开发说明和示例代码如下。

    • 计算MQTT连接参数clientIdusernamepassword,并将usernamepassword设置到MqttConnectOptions对象中。
      final private String PRODUCTKEY = "a11xsrW****";
      final private String DEVICENAME = "paho_android";
      final private String DEVICESECRET = "tLMT9QWD36U2SArglGqcHCDK9rK9****";
      
      /* 获取MQTT建连信息clientId, username, password */
      AiotMqttOption aiotMqttOption = new AiotMqttOption().getMqttOption(PRODUCTKEY, DEVICENAME, DEVICESECRET);
      if (aiotMqttOption == null) {
          Log.e(TAG, "device info error");
      } else {
          clientId = aiotMqttOption.getClientId();
          userName = aiotMqttOption.getUsername();
          passWord = aiotMqttOption.getPassword();
      }
      
      /* 创建MqttConnectOptions对象并配置username和password */
      MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
      mqttConnectOptions.setUserName(userName);
      mqttConnectOptions.setPassword(passWord.toCharArray());
    • 接入物联网平台。

      创建一个MqttAndroidClient对象,设置回调接口,然后使用mqttConnectOptions调用connect方法,即可建立连接。

      /* 创建MqttAndroidClient对象, 并设置回调接口 */
      mqttAndroidClient = new MqttAndroidClient(getApplicationContext(), host, clientId);
      mqttAndroidClient.setCallback(new MqttCallback() {
          @Override
          public void connectionLost(Throwable cause) {
              Log.i(TAG, "connection lost");
          }
      
          @Override
          public void messageArrived(String topic, MqttMessage message) throws Exception {
              Log.i(TAG, "topic: " + topic + ", msg: " + new String(message.getPayload()));
          }
      
          @Override
          public void deliveryComplete(IMqttDeliveryToken token) {
              Log.i(TAG, "msg delivered");
          }
      });
      
      /* MQTT建连 */
      try {
          mqttAndroidClient.connect(mqttConnectOptions, null, new IMqttActionListener() {
              @Override
              public void onSuccess(IMqttToken asyncActionToken) {
                  Log.i(TAG, "connect succeed");
      
                  subscribeTopic(SUB_TOPIC);
              }
      
              @Override
              public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                  Log.i(TAG, "connect failed");
              }
          });
      
      } catch (MqttException e) {
          e.printStackTrace();
      }
    • 发布消息。封装publish方法,用于向Topic /${prodcutKey}/${deviceName}/user/update发布指定payload的消息。
      public void publishMessage(String payload) {
          try {
              if (mqttAndroidClient.isConnected() == false) {
                  mqttAndroidClient.connect();
              }
      
              MqttMessage message = new MqttMessage();
              message.setPayload(payload.getBytes());
              message.setQos(0);
              mqttAndroidClient.publish(PUB_TOPIC, message,null, new IMqttActionListener() {
                  @Override
                  public void onSuccess(IMqttToken asyncActionToken) {
                      Log.i(TAG, "publish succeed!");
                  }
      
                  @Override
                  public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                      Log.i(TAG, "publish failed!");
                  }
              });
          } catch (MqttException e) {
              Log.e(TAG, e.toString());
              e.printStackTrace();
          }
      }

      通信Topic介绍,请参见什么是Topic

    • 封装subscribe方法,用于实现订阅指定Topic,获取云端下发的消息。
      public void subscribeTopic(String topic) {
          try {
              mqttAndroidClient.subscribe(topic, 0, null, new IMqttActionListener() {
                  @Override
                  public void onSuccess(IMqttToken asyncActionToken) {
                      Log.i(TAG, "subscribed succeed");
                  }
      
                  @Override
                  public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                      Log.i(TAG, "subscribed failed");
                  }
              });
      
          } catch (MqttException e) {
              e.printStackTrace();
          }
      }

    关于设备、服务器和物联网平台的通信方式介绍,请参见通信方式概述

  4. 编译项目。

示例Demo

使用Demo代码程序接入物联网平台。

  1. 下载代码Demo包,并解压缩。
  2. aiot-android-demo导入Android Studio。
  3. app/src/main/java/com.linkkit.aiot_android_demo下的MainActivity文件中,替换设备信息为您的设备信息。
    • productKeydeviceNamedeviceSecret替换为您的设备证书信息。
    • final String host = "tcp://" + PRODUCTKEY + ".iot-as-mqtt.cn-shanghai.aliyuncs.com:443";中的地域代码(cn-shanghai)替换为您的物联网平台设备所在地域代码。地域代码表达方法,请参见地域和可用区
  4. 构建应用,并运行。
    运行成功后,可在Logcat中查看本地日志。
    2019-12-04 19:44:01.824 5952-5987/com.linkkit.aiot_android_demo W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
    2019-12-04 19:44:01.829 5952-5987/com.linkkit.aiot_android_demo D/EGL_emulation: eglCreateContext: 0xec073240: maj 3 min 0 rcv 3
    2019-12-04 19:44:01.830 5952-5987/com.linkkit.aiot_android_demo D/EGL_emulation: eglMakeCurrent: 0xec073240: ver 3 0 (tinfo 0xec09b470)
    2019-12-04 19:44:01.852 5952-5987/com.linkkit.aiot_android_demo W/Gralloc3: mapper 3.x is not supported
    2019-12-04 19:44:01.854 5952-5987/com.linkkit.aiot_android_demo D/HostConnection: createUnique: call
    ...
    ...
    2019-12-04 19:44:01.860 5952-5987/com.linkkit.aiot_android_demo D/eglCodecCommon: allocate: Ask for block of size 0x1000
    2019-12-04 19:44:01.861 5952-5987/com.linkkit.aiot_android_demo D/eglCodecCommon: allocate: ioctl allocate returned offset 0x3ff706000 size 0x2000
    2019-12-04 19:44:01.897 5952-5987/com.linkkit.aiot_android_demo D/EGL_emulation: eglMakeCurrent: 0xec073240: ver 3 0 (tinfo 0xec09b470)
    2019-12-04 19:44:02.245 5952-6023/com.linkkit.aiot_android_demo D/AlarmPingSender: Register alarmreceiver to MqttServiceMqttService.pingSender.a11xsrW****.paho_android|timestamp=1575459841629,_v=sdk-android-1.0.0,securemode=2,signmethod=hmacsha256|
    2019-12-04 19:44:02.256 5952-6023/com.linkkit.aiot_android_demo D/AlarmPingSender: Schedule next alarm at 1575459902256
    2019-12-04 19:44:02.256 5952-6023/com.linkkit.aiot_android_demo D/AlarmPingSender: Alarm scheule using setExactAndAllowWhileIdle, next: 60000
    2019-12-04 19:44:02.272 5952-5952/com.linkkit.aiot_android_demo I/AiotMqtt: connect succeed
    2019-12-04 19:44:02.301 5952-5952/com.linkkit.aiot_android_demo I/AiotMqtt: subscribed succeed

    物联网平台控制台上,可查看设备状态和日志。

    • 选择设备管理 > 设备,可看到该设备的状态会显示为在线
    • 选择监控管理 > 日志服务,可查看设备行为分析上行消息分析日志。