全部產品
Search
文件中心

IoT Platform:Paho-MQTT Android接入樣本

更新時間:Jun 30, 2024

本文介紹如何使用Paho Android Service接入阿里雲物聯網平台,並進行資料收發。

前提條件

已在物聯網平台控制台,對應執行個體下,建立產品和裝置,並擷取MQTT接入網域名稱和裝置認證資訊(ProductKey、DeviceName和DeviceSecret)。具體操作,請參見:

背景資訊

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工程。
    重要 在應用build.gradle檔案中的targetSdkVersion需要小於或等於30。若不符合要求,請進行修正。
  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. 下載android_sameple_code.zip,然後解壓擷取阿里雲提供的計算MQTT串連參數所需的源碼檔案AiotMqttOption.java

    AiotMqttOption.java檔案中定義了AiotMqttOption()類,類說明如下:

    • 原型:
      class AiotMqttOption
    • 功能:

      用於計算裝置接入物聯網平台的MQTT串連參數usernamepasswordclientid

    • 成員:
      類型定義方法描述
      public AiotMqttOptiongetMqttOption(String productKey, String deviceName, String deviceSecret)

      根據裝置的productKeydeviceNamedeviceSecret計算出MQTT串連參數usernamepasswordclientid

      public StringgetUsername()

      用於擷取MQTT建連參數username

      public StringgetPassword()

      用於擷取MQTT建連參數password

      public StringgetClientid()

      用於擷取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";中的值為對應的接入網域名稱。
      • 對於新版公用執行個體和企業版執行個體:final String host = "tcp://" + "${企業版執行個體下MQTT接入網域名稱}"

        您可登入物聯網平台控制台,在執行個體概覽頁,找到並單擊對應執行個體,進入執行個體詳情頁面,單擊右上方的查看開發配置擷取。具體操作,請參見查看和配置執行個體終端節點資訊(Endpoint)

      • 對於舊版公用執行個體:

        替換地區代碼(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

    登入物聯網平台控制台,可查看裝置狀態和日誌。

    • 選擇裝置管理 > 裝置,可看到該裝置的狀態顯示為線上
    • 選擇監控營運 > Log Service,可查看雲端作業記錄裝置本地日誌日誌。詳細內容,請參見雲端作業記錄裝置本地日誌

錯誤碼

如果裝置通過MQTT協議接入物聯網平台失敗,請根據錯誤碼排查問題。服務端錯誤碼說明,請參見錯誤排查