帮你快速理解、总结文档立即下载

Android 智能设备

最近更新时间:2026-09-15 15:34:03
我的收藏
本文将介绍如何在 Android 平台基于腾讯云物联网设备端 Android SDK,使用动态注册(Dynamic Register)能力,在产品量产阶段由设备自动从云端获取设备密钥,减少客户手动逐个烧录设备密钥的工作量,提升量产效率。

关键概念

动态注册用于产品量产过程中,在控制台批量创建设备后,设备根据 productIdproductSecretdeviceId,从后台获取设备密钥(deviceSecret)。该机制减少客户手动逐个烧录设备密钥的工作量,提升量产效率。

适用场景

量产阶段需要批量激活大量设备,逐一烧录设备密钥成本过高。
设备出厂时只烧录产品级别的 productSecret,由设备首次联网时自行换取设备密钥。
设备端希望密钥不固化在产线,降低密钥泄漏风险。

名词解释

名词
说明
productId
产品标识,在控制台创建产品时生成。
productSecret
产品密钥,产品级别,用于动态注册时对请求进行 HMAC-SHA256 签名与对响应进行 AES-128-CBC 解密。
deviceId
设备名称,在控制台批量创建设备时由平台生成或自定义,需与控制台保持一致。
deviceSecret
设备密钥,动态注册成功后由云端下发,后续登录时使用。

前提条件

在接入动态注册功能前,请您先完成以下准备工作:
1. 登录 物联网开发平台控制台,创建产品并记录 productIdproductSecret
2. 在控制台批量创建设备,记录每台设备的 deviceId。动态注册要求设备名必须先在控制台预创建,否则会返回 Pre create mode: device not exists
3. 在产品详情页开启动态注册功能。如果未开启,设备端会收到 Not support dynamic device register, please check setting first
4. 已完成 SDK 初始化(initSDK)流程。动态注册仅需 SDK 初始化,不依赖登录成功

接入步骤

本节介绍如何调用 SDK 完成动态注册的核心调用:初始化 SDK、发起注册请求、在回调中获取设备密钥、使用密钥完成登录

步骤 1:控制台预创建设备并开启动态注册

1. 登录 物联网开发平台控制台,在产品列表中单击创建的产品名称进入详情。
2. 设备页面单击批量新建设备,生成若干 deviceId。动态注册时传入的 deviceId 必须在此列表中存在。

3. 在产品详情页的动态注册开关处,确认功能已开启。关闭状态下注册请求会被云端拒绝。


步骤 2:初始化 SDK

调用 initSDK 完成 SDK 初始化,动态注册依赖 SDK 内部的 HTTP/TLS 能力。初始化成功返回 0TXIoTError.SUCCESS)。
TXIoTDeviceEngine.Config config = new TXIoTDeviceEngine.Config();
config.storagePath = getFilesDir().getAbsolutePath();
config.logLevel = TXIoTDeviceEngine.LogLevel.INFO;

int ret = TXIoTDeviceEngine.getInstance(applicationContext).initSDK(config);
if (ret != TXIoTError.SUCCESS) {
Log.e(TAG, "initSDK failed: " + ret);
return;
}

步骤 3:发起动态注册请求

调用 dynamicRegister 发起注册,入参 DynamicRegisterParams
字段
说明
productId
产品标识,必填。
deviceId
设备名称,必填,需在控制台预创建。
productSecret
产品密钥,必填,长度需 ≥ 16字节(AES-128 密钥长度要求)。
回调 TXIoTValueCallback<String> 参数说明:
回调
说明
onSuccess(String deviceKey)
注册成功,deviceKey 为云端下发的设备密钥,后续登录时作为 deviceSecret 使用。
onError(int code, String desc)
注册失败,code 为错误码,desc 为错误描述。常见错误码详见 常见问题。
说明:
dynamicRegister 是异步接口,注册结果通过回调异步返回。
同一时刻只允许有一个注册请求在途,重复调用会返回 TXIoTError.DYNAMIC_REGISTER_BUSY
TXIoTDeviceEngine.DynamicRegisterParams params = new TXIoTDeviceEngine.DynamicRegisterParams();
params.productId = "YOUR_PRODUCT_ID";
params.deviceId = "YOUR_DEVICE_ID";
params.productSecret = "YOUR_PRODUCT_SECRET";

TXIoTDeviceEngine.getInstance(applicationContext).dynamicRegister(params, new TXIoTValueCallback<String>() {
@Override
public void onSuccess(String deviceKey) {
Log.i(TAG, "dynamic register success, deviceKey=" + deviceKey);
// 见步骤 4:使用该密钥登录
}

@Override
public void onError(int code, String desc) {
Log.e(TAG, "dynamic register failed: " + code + ", " + desc);
}
});

步骤 4:使用获取的密钥登录

动态注册成功后,在回调中拿到 deviceKey,将其作为 deviceSecret 调用 login 完成登录。建议将密钥持久化到本地存储,避免每次开机都重新注册。
@Override
public void onSuccess(String deviceKey) {
Log.i(TAG, "dynamic register success, deviceKey=" + deviceKey);

// 建议持久化 deviceKey,下次开机直接复用,无需再次动态注册
// saveDeviceSecretToStorage(deviceKey);

TXIoTDeviceEngine.DeviceInfo deviceInfo = new TXIoTDeviceEngine.DeviceInfo();
deviceInfo.productId = "YOUR_PRODUCT_ID";
deviceInfo.deviceId = "YOUR_DEVICE_ID";
deviceInfo.deviceSecret = deviceKey; // 使用动态注册获取的密钥
deviceInfo.region = "ap-guangzhou";

TXIoTDeviceEngine.getInstance(applicationContext).login(deviceInfo, new TXIoTCallback() {
@Override
public void onSuccess() {
Log.i(TAG, "login success");
}

@Override
public void onError(int code, String desc) {
Log.e(TAG, "login failed: " + code + ", " + desc);
}
});
}
注意:
deviceKey 属于设备敏感凭证,建议持久化到应用私有目录或 Android Keystore 等安全存储中,避免明文保存或提交到代码仓库。

完整示例代码

以下示例整合上述步骤,演示在 Android 应用中完成 SDK 初始化、动态注册、并使用获取的密钥登录的完整流程。
package com.example.iotdemo;

import android.content.Context;
import android.util.Log;

import com.tencent.liteav.iot.TXIoTCallback;
import com.tencent.liteav.iot.TXIoTDeviceEngine;
import com.tencent.liteav.iot.TXIoTError;
import com.tencent.liteav.iot.TXIoTValueCallback;

public class DynamicRegisterHelper {

private static final String TAG = "DynamicRegister";

private final TXIoTDeviceEngine mEngine;
private final String mProductId;
private final String mDeviceId;
private final String mProductSecret;

public DynamicRegisterHelper(Context context, String productId, String deviceId, String productSecret) {
mEngine = TXIoTDeviceEngine.getInstance(context.getApplicationContext());
mProductId = productId;
mDeviceId = deviceId;
mProductSecret = productSecret;
}

/** 初始化 SDK 并开始动态注册 */
public void start() {
// 1. 初始化 SDK
TXIoTDeviceEngine.Config config = new TXIoTDeviceEngine.Config();
config.logLevel = TXIoTDeviceEngine.LogLevel.INFO;

int ret = mEngine.initSDK(config);
if (ret != TXIoTError.SUCCESS) {
Log.e(TAG, "initSDK failed: " + ret);
return;
}

// 2. 发起动态注册
TXIoTDeviceEngine.DynamicRegisterParams params = new TXIoTDeviceEngine.DynamicRegisterParams();
params.productId = mProductId;
params.deviceId = mDeviceId;
params.productSecret = mProductSecret;

mEngine.dynamicRegister(params, new TXIoTValueCallback<String>() {
@Override
public void onSuccess(String deviceKey) {
Log.i(TAG, "dynamic register success, deviceKey=" + deviceKey);
loginWithDeviceKey(deviceKey);
}

@Override
public void onError(int code, String desc) {
Log.e(TAG, "dynamic register failed: " + code + ", " + desc);
}
});
}

/** 3. 使用动态注册获取的密钥登录 */
private void loginWithDeviceKey(String deviceKey) {
// 建议持久化 deviceKey,下次开机直接复用,无需再次动态注册
// saveDeviceSecretToStorage(deviceKey);

TXIoTDeviceEngine.DeviceInfo deviceInfo = new TXIoTDeviceEngine.DeviceInfo();
deviceInfo.productId = mProductId;
deviceInfo.deviceId = mDeviceId;
deviceInfo.deviceSecret = deviceKey;
deviceInfo.region = "ap-guangzhou";

mEngine.login(deviceInfo, new TXIoTCallback() {
@Override
public void onSuccess() {
Log.i(TAG, "login success");
}

@Override
public void onError(int code, String desc) {
Log.e(TAG, "login failed: " + code + ", " + desc);
}
});
}

/** 4. 业务完成后释放资源 */
public void release() {
mEngine.logout(null);
mEngine.uninitSDK();
}
}
说明:
1. 动态注册仅依赖 initSDK 成功,无需提前登录;获取到 deviceKey 后再执行 login
2. Demo 的 LoginActivity 已集成动态注册流程,可参考其实现。

编译并运行

Demo 已开源,仓库地址:github.com/Tencent-RTC/Tencent_IoT_Device,Android Demo 位于顶层 Android/ 目录。
1. 使用 git clone 将开源 Demo 从 GitHub 克隆到本地。
2. 打开 Android Studio,点击 Open 导入工程,等待 Gradle Sync 完成。
3. 连接 Android 真机,点击工具栏 Run 编译运行。
# 也可在控制台打包 APK 后发送到手机安装
./gradlew :app:assembleDebug
4. 观察日志输出,出现以下内容代表动态注册与登录均成功。
dynamic register success, deviceKey=xxxxxxxxxxxxx
login success

常见问题

现象
排查建议
动态注册回调提示 Not support dynamic device register, please check setting first
动态注册功能未在控制台开启。请在产品详情页打开动态注册开关后再试。
动态注册回调提示 Pre create mode: device not exists
传入的 deviceId 在控制台未预创建。请先在控制台批量创建对应设备,确保 deviceId 与控制台一致。
动态注册回调提示 Device has been activated
该设备已动态注册过且密钥已激活。已注册的设备名再次动态注册会被拒绝,请使用上次获取的密钥登录。
动态注册获取的密钥未登录,再次注册拿到新密钥。
如果动态注册获取的密钥未用于登录,下次仍可执行动态注册,但会获取到新的密钥,之前的密钥同时失效,只能使用最新获取的密钥。
dynamicRegister 返回 DYNAMIC_REGISTER_BUSY(-20)
上一次注册请求仍在途。SDK 同一时刻只允许一个注册请求,请等待回调返回后再发起新请求。
dynamicRegister 返回 INVALID_ARGUMENT(-3)
检查 productIddeviceId 是否为空或过长;productSecret 长度是否 ≥ 16字节(AES-128 密钥要求)。
dynamicRegister 返回 NOT_INITIALIZED(-4)
确认在调用前已成功调用 initSDK
DYNAMIC_REGISTER_REQUEST_FAILED(-21)
HTTP 请求失败或云端返回错误。请检查网络、productSecret 是否正确、签名是否匹配;查看日志中的错误描述获取具体原因。
DYNAMIC_REGISTER_RESPONSE_INVALID(-22)
云端响应格式异常或解密失败。常见原因为 productSecret 与控制台不一致(解密失败),或响应被中间代理改写。

联系我们

如果您在接入或使用过程中有任何疑问或者建议,欢迎 联系我们 提交反馈。