注意:说明:
注意:设备分享与设备绑定是两条独立链路:绑定把设备纳入某个家庭,需要业务后台签发的设备绑定签名;分享把已绑定设备的使用权授予另一个账号,只需要设备拥有者生成的分享 Token,不改变设备的家庭归属。
一、前提条件
在使用设备分享能力前,请确保已完成以下准备工作:
·已开通腾讯云物联网相关服务,并在控制台完成实例、应用和设备的准备工作。可参见 开通服务。
·已在客户端工程中集成 IoT 应用端 SDK 并完成登录。可参见 Android SDK 集成与登录、iOS SDK 集成与登录、小程序 SDK 集成与登录、鸿蒙 SDK 集成与登录。
·分享方:目标设备已绑定到当前登录账户名下,且当前用户是设备拥有者。可参见 设备绑定。
·接收方:已获得设备拥有者提供的分享 Token,以及设备的 productId 与 deviceName。
二、获取设备管理对象
分享相关接口均由 TXIoTDeviceManager 提供。登录成功后,通过 TXIoTEngine 单例获取该对象,可长期持有。
AndroidiOS小程序鸿蒙TXIoTEngine iotEngine = TXIoTEngine.getInstance(context);TXIoTDeviceManager deviceManager = iotEngine.getDeviceManager();if (deviceManager == null) { // SDK 未登录或登录已过期,请先完成登录。 return;}TXIoTDeviceManager *deviceManager = [[TXIoTEngine getInstance] getDeviceManager];if (deviceManager == nil) { // SDK 未登录或登录已过期,请先完成登录。 return;}const { TXIoTEngine } = requirePlugin('tx-iot-sdk');// getInstance 为异步方法,首次调用会等待内部模块加载完成。const iotEngine = await TXIoTEngine.getInstance();const deviceManager = iotEngine.getDeviceManager();if (deviceManager == null) { // SDK 未登录或登录已过期,请先完成登录。 return;}import { getIoTEngineInstance, TXIoTEngine } from '@tencentcloud/liteavsdk_iot'const iotEngine: TXIoTEngine = getIoTEngineInstance()const deviceManager = iotEngine.getDeviceManager()if (deviceManager == null) { // SDK 未登录或登录已过期,请先完成登录。 return}
注意:说明:
注意:getDeviceManager 返回空值(Android、小程序与鸿蒙为 null,iOS 为 nil)表示 SDK 尚未登录或登录已过期。请在登录成功回调之后再获取该对象,不要在 App 启动阶段提前缓存。
三、分享模型
设备分享用于把单台已绑定设备的使用权授予其他账号,典型场景是把门口摄像头分享给家政人员,或把设备临时授权给亲友查看。
·分享不改变设备的家庭归属,被分享用户不会成为设备所属家庭的成员。
·被分享设备不出现在被分享用户的 getDeviceList 结果中,需通过 getDeviceListSharedWithMe 单独查询。
·分享关系可由设备拥有者单方面撤销,也可由被分享用户自行取消。
注意:设备分享 Token 与家庭邀请 Token 是两种不同的凭据,不可混用:家庭邀请 Token 用于加入家庭并获得该家庭下所有设备的权限,设备分享 Token 只对指定的一台设备生效。两者均属敏感凭据,请通过可信渠道传递,并避免在日志中明文输出。
完整分享流程如下:
1. 设备拥有者调用 createDeviceSharingToken,传入 familyId 与目标 deviceId,得到分享 Token。
2. 拥有者通过业务自有渠道(如二维码、站内消息)把 Token 与设备的 productId、deviceName 一并发送给被分享用户。
3. 被分享用户登录 SDK 后调用 bindDeviceSharedWithMe,传入 deviceId 与 Token 完成接收。
4. 被分享用户通过 getDeviceListSharedWithMe 查询自己收到的共享设备。
四、创建分享 Token 与接受分享
| 方法 | 说明 |
| createDeviceSharingToken | 设备拥有者生成分享 Token,需传入 familyId 与 deviceId。由拥有者调用,被分享用户无此权限。 |
| bindDeviceSharedWithMe | 被分享用户使用 Token 接收共享设备,需同时传入设备的 deviceId 与 Token,两者不匹配将绑定失败。 |
AndroidiOS小程序鸿蒙// 设备拥有者:创建分享 Token。deviceManager.createDeviceSharingToken(familyId, deviceId, new TXIoTCallback<String>() { @Override public void onSuccess(String shareToken) { // 将 shareToken 与 deviceId 一并通过业务自有渠道发送给被分享用户。 } @Override public void onError(TXIoTErrorCode errorCode, String errorMessage) { // 创建分享 Token 失败,请根据错误码和错误信息处理。 }});// 被分享用户:使用 Token 接收共享设备。deviceManager.bindDeviceSharedWithMe(deviceId, shareToken, new TXIoTCallback<Void>() { @Override public void onSuccess(Void result) { // 接收成功,可调用 getDeviceListSharedWithMe 刷新共享设备列表。 } @Override public void onError(TXIoTErrorCode errorCode, String errorMessage) { // 接收失败,请检查 Token 是否过期,以及 deviceId 与 Token 是否匹配。 }});// 设备拥有者:创建分享 Token。TXIoTCallback<NSString *> *shareCallback = [[TXIoTCallback alloc] init];shareCallback.onSuccess = ^(NSString *shareToken) { // 将 shareToken 与 deviceId 一并通过业务自有渠道发送给被分享用户。};shareCallback.onError = ^(TXIoTErrorCode errorCode, NSString *errorMessage) { // 创建分享 Token 失败,请根据错误码和错误信息处理。};[deviceManager createDeviceSharingToken:familyId deviceId:deviceId callback:shareCallback];// 被分享用户:使用 Token 接收共享设备。TXIoTVoidCallback *bindSharedCallback = [[TXIoTVoidCallback alloc] init];bindSharedCallback.onSuccess = ^{ // 接收成功,可调用 getDeviceListSharedWithMe 刷新共享设备列表。};bindSharedCallback.onError = ^(TXIoTErrorCode errorCode, NSString *errorMessage) { // 接收失败,请检查 Token 是否过期,以及 deviceId 与 Token 是否匹配。};[deviceManager bindDeviceSharedWithMe:deviceId shareToken:shareToken callback:bindSharedCallback];// 设备拥有者:创建分享 Token。try { const shareToken = await deviceManager.createDeviceSharingToken(familyId, deviceId); // 将 shareToken 与 deviceId 一并通过业务自有渠道发送给被分享用户。} catch (err) { // 创建分享 Token 失败,请根据 err.code 和 err.message 处理。}// 被分享用户:使用 Token 接收共享设备。try { await deviceManager.bindDeviceSharedWithMe(deviceId, shareToken); // 接收成功,可调用 getDeviceListSharedWithMe 刷新共享设备列表。} catch (err) { // 接收失败,请检查 Token 是否过期,以及 deviceId 与 Token 是否匹配。}// 设备拥有者:创建分享 Token。deviceManager.createDeviceSharingToken(familyId, deviceId, { onSuccess: (shareToken) => { // 将 shareToken 与 deviceId 一并通过业务自有渠道发送给被分享用户。 }, onError: (errorCode, errorMessage) => { // 创建分享 Token 失败,请根据错误码和错误信息处理。 }})// 被分享用户:使用 Token 接收共享设备。deviceManager.bindDeviceSharedWithMe(deviceId, shareToken, { onSuccess: () => { // 接收成功,可调用 getDeviceListSharedWithMe 刷新共享设备列表。 }, onError: (errorCode, errorMessage) => { // 接收失败,请检查 Token 是否过期,以及 deviceId 与 Token 是否匹配。 }})
五、拥有者管理共享用户
设备拥有者可查询某台设备已分享给哪些用户,并撤销指定用户的权限。
| 方法 | 说明 |
| getDeviceSharedUsers | 查询指定设备的共享用户列表,返回 TXIoTUserInfo 列表,其中 deviceBindTime 为该用户接收分享的时间。 |
| removeDeviceSharedUser | 撤销指定用户对该设备的访问权限,userId 取自 getDeviceSharedUsers 的返回结果。 |
AndroidiOS小程序鸿蒙// 先查询共享用户列表,再基于返回的 userId 执行撤销。deviceManager.getDeviceSharedUsers(deviceId, new TXIoTCallback<List<TXIoTUserInfo>>() { @Override public void onSuccess(List<TXIoTUserInfo> userList) { for (TXIoTUserInfo user : userList) { // user.userId / user.nickName / user.avatarUrl / user.deviceBindTime } if (!userList.isEmpty()) { String userId = userList.get(0).userId; deviceManager.removeDeviceSharedUser(deviceId, userId, new TXIoTCallback<Void>() { @Override public void onSuccess(Void result) { // 撤销成功。 } @Override public void onError(TXIoTErrorCode errorCode, String errorMessage) { // 撤销失败,请根据错误码和错误信息处理。 } }); } } @Override public void onError(TXIoTErrorCode errorCode, String errorMessage) { // 查询共享用户失败,请根据错误码和错误信息处理。 }});// 先查询共享用户列表,再基于返回的 userId 执行撤销。TXIoTCallback<NSArray<TXIoTUserInfo *> *> *usersCallback = [[TXIoTCallback alloc] init];usersCallback.onSuccess = ^(NSArray<TXIoTUserInfo *> *userList) { if (userList.count == 0) { return; } NSString *userId = userList.firstObject.userId; TXIoTVoidCallback *removeCallback = [[TXIoTVoidCallback alloc] init]; removeCallback.onSuccess = ^{ // 撤销成功。 }; removeCallback.onError = ^(TXIoTErrorCode errorCode, NSString *errorMessage) { // 撤销失败,请根据错误码和错误信息处理。 }; [deviceManager removeDeviceSharedUser:deviceId userId:userId callback:removeCallback];};usersCallback.onError = ^(TXIoTErrorCode errorCode, NSString *errorMessage) { // 查询共享用户失败,请根据错误码和错误信息处理。};[deviceManager getDeviceSharedUsers:deviceId callback:usersCallback];// 先查询共享用户列表,再基于返回的 userId 执行撤销。try { const userList = await deviceManager.getDeviceSharedUsers(deviceId); for (const user of userList) { // user.userId / user.nickName / user.avatarUrl / user.deviceBindTime } if (userList.length > 0) { const userId = userList[0].userId; await deviceManager.removeDeviceSharedUser(deviceId, userId); // 撤销成功。 }} catch (err) { // 查询或撤销失败,请根据 err.code 和 err.message 处理。}// 先查询共享用户列表,再基于返回的 userId 执行撤销。deviceManager.getDeviceSharedUsers(deviceId, { onSuccess: (userList) => { for (const user of userList) { // user.userId / user.nickName / user.avatarUrl / user.deviceBindTime } if (userList.length > 0) { const userId = userList[0].userId deviceManager.removeDeviceSharedUser(deviceId, userId, { onSuccess: () => { // 撤销成功。 }, onError: (errorCode, errorMessage) => { // 撤销失败,请根据错误码和错误信息处理。 } }) } }, onError: (errorCode, errorMessage) => { // 查询共享用户失败,请根据错误码和错误信息处理。 }})
六、被分享用户管理共享设备
被分享用户可分页查询所有分享给自己的设备,也可主动取消接收。
| 方法 | 说明 |
| getDeviceListSharedWithMe | 分页查询所有分享给当前用户的设备,不需要传 familyId。分页规则与 getDeviceList 一致:首次传空字符串,nextPageToken 为空字符串表示已是最后一页。 |
| unbindDeviceSharedWithMe | 取消接收分享的设备,只需传入 deviceId。取消后不再拥有该设备的访问权限,但不影响设备与其拥有者的绑定关系。 |
AndroidiOS小程序鸿蒙// 查询分享给我的设备(首次传空字符串)。deviceManager.getDeviceListSharedWithMe("", new TXIoTCallback<TXIoTPageResult<TXIoTDeviceInfo>>() { @Override public void onSuccess(TXIoTPageResult<TXIoTDeviceInfo> pageResult) { List<TXIoTDeviceInfo> sharedDevices = pageResult.dataList; String nextPageToken = pageResult.nextPageToken; // nextPageToken 非空时原样回传以获取下一页。 } @Override public void onError(TXIoTErrorCode errorCode, String errorMessage) { // 查询共享设备列表失败,请根据错误码和错误信息处理。 }});// 取消接收共享设备。deviceManager.unbindDeviceSharedWithMe(deviceId, new TXIoTCallback<Void>() { @Override public void onSuccess(Void result) { // 取消成功。 } @Override public void onError(TXIoTErrorCode errorCode, String errorMessage) { // 取消失败,请根据错误码和错误信息处理。 }});// 查询分享给我的设备(首次传空字符串)。TXIoTCallback<TXIoTPageResult<TXIoTDeviceInfo *> *> *sharedListCallback = [[TXIoTCallback alloc] init];sharedListCallback.onSuccess = ^(TXIoTPageResult<TXIoTDeviceInfo *> *pageResult) { NSArray<TXIoTDeviceInfo *> *sharedDevices = pageResult.dataList; NSString *nextPageToken = pageResult.nextPageToken; // nextPageToken 非空时原样回传以获取下一页。};sharedListCallback.onError = ^(TXIoTErrorCode errorCode, NSString *errorMessage) { // 查询共享设备列表失败,请根据错误码和错误信息处理。};[deviceManager getDeviceListSharedWithMe:@"" callback:sharedListCallback];// 取消接收共享设备。TXIoTVoidCallback *unbindSharedCallback = [[TXIoTVoidCallback alloc] init];unbindSharedCallback.onSuccess = ^{ // 取消成功。};unbindSharedCallback.onError = ^(TXIoTErrorCode errorCode, NSString *errorMessage) { // 取消失败,请根据错误码和错误信息处理。};[deviceManager unbindDeviceSharedWithMe:deviceId callback:unbindSharedCallback];// 查询分享给我的设备(首次传空字符串)。try { const pageResult = await deviceManager.getDeviceListSharedWithMe(''); const sharedDevices = pageResult.dataList; const nextPageToken = pageResult.nextPageToken; // nextPageToken 非空时原样回传以获取下一页。} catch (err) { // 查询共享设备列表失败,请根据 err.code 和 err.message 处理。}// 取消接收共享设备。try { await deviceManager.unbindDeviceSharedWithMe(deviceId); // 取消成功。} catch (err) { // 取消失败,请根据 err.code 和 err.message 处理。}// 查询分享给我的设备(首次传空字符串)。deviceManager.getDeviceListSharedWithMe('', { onSuccess: (pageResult) => { const sharedDevices = pageResult.dataList const nextPageToken = pageResult.nextPageToken // nextPageToken 非空时原样回传以获取下一页。 }, onError: (errorCode, errorMessage) => { // 查询共享设备列表失败,请根据错误码和错误信息处理。 }})// 取消接收共享设备。deviceManager.unbindDeviceSharedWithMe(deviceId, { onSuccess: () => { // 取消成功。 }, onError: (errorCode, errorMessage) => { // 取消失败,请根据错误码和错误信息处理。 }})
七、错误处理
设备分享链路常见的错误码如下,完整定义参见 TXIoTErrorCode。
AndroidiOS小程序鸿蒙
| 错误码 | 说明 | 建议处理方式 |
| ERR_INVALID_PARAMETER | 参数不合法。 | 检查 productId、deviceName、familyId、分享 Token、userId 是否为空。 |
| ERR_INVALID_ACCESS_TOKEN | 登录凭证无效。 | 重新登录 SDK,并重新获取设备管理对象。 |
| ERR_UNAUTHORIZED_OPERATION | 当前用户无权限。 | 创建分享 Token 与撤销共享用户仅设备拥有者可执行,被分享用户调用会返回该错误。 |
| ERR_DEVICE_NOT_EXIST | 设备不存在。 | 检查 productId 与 deviceName 是否正确,以及设备是否仍处于绑定状态。 |
| ERR_DEVICE_OFFLINE | 设备离线。 | 分享关系本身不受在线状态影响;若后续拉流或控制失败,引导用户检查设备网络。 |
| ERR_RATE_LIMITED | 请求被限频。 | 降低调用频率,避免高频轮询共享用户列表或共享设备列表。 |
| 错误码 | 说明 | 建议处理方式 |
| TXIoTErrorCodeInvalidParameter | 参数不合法。 | 检查 productId、deviceName、familyId、分享 Token、userId 是否为空。 |
| TXIoTErrorCodeInvalidAccessToken | 登录凭证无效。 | 重新登录 SDK,并重新获取设备管理对象。 |
| TXIoTErrorCodeUnauthorizedOperation | 当前用户无权限。 | 创建分享 Token 与撤销共享用户仅设备拥有者可执行,被分享用户调用会返回该错误。 |
| TXIoTErrorCodeDeviceNotExist | 设备不存在。 | 检查 productId 与 deviceName 是否正确,以及设备是否仍处于绑定状态。 |
| TXIoTErrorCodeDeviceOffline | 设备离线。 | 分享关系本身不受在线状态影响;若后续拉流或控制失败,引导用户检查设备网络。 |
| TXIoTErrorCodeRateLimited | 请求被限频。 | 降低调用频率,避免高频轮询共享用户列表或共享设备列表。 |
| 错误码 | 说明 | 建议处理方式 |
| InvalidParameter | 参数不合法。 | 检查 productId、deviceName、familyId、分享 Token、userId 是否为空。 |
| InvalidAccessToken | 登录凭证无效。 | 重新登录 SDK,并重新获取设备管理对象。 |
| UnauthorizedOperation | 当前用户无权限。 | 创建分享 Token 与撤销共享用户仅设备拥有者可执行,被分享用户调用会返回该错误。 |
| DeviceNotExist | 设备不存在。 | 检查 productId 与 deviceName 是否正确,以及设备是否仍处于绑定状态。 |
| DeviceOffline | 设备离线。 | 分享关系本身不受在线状态影响;若后续拉流或控制失败,引导用户检查设备网络。 |
| RateLimited | 请求被限频。 | 降低调用频率,避免高频轮询共享用户列表或共享设备列表。 |
| 错误码 | 说明 | 建议处理方式 |
| ERR_INVALID_PARAMETER | 参数不合法。 | 检查 productId、deviceName、familyId、分享 Token、userId 是否为空。 |
| ERR_INVALID_ACCESS_TOKEN | 登录凭证无效。 | 重新登录 SDK,并重新获取设备管理对象。 |
| ERR_UNAUTHORIZED_OPERATION | 当前用户无权限。 | 创建分享 Token 与撤销共享用户仅设备拥有者可执行,被分享用户调用会返回该错误。 |
| ERR_DEVICE_NOT_EXIST | 设备不存在。 | 检查 productId 与 deviceName 是否正确,以及设备是否仍处于绑定状态。 |
| ERR_DEVICE_OFFLINE | 设备离线。 | 分享关系本身不受在线状态影响;若后续拉流或控制失败,引导用户检查设备网络。 |
| ERR_RATE_LIMITED | 请求被限频。 | 降低调用频率,避免高频轮询共享用户列表或共享设备列表。 |
八、设备分享和把成员加入家庭有什么区别?
两者的授权粒度不同:
·加入家庭:被邀请用户成为家庭成员,可访问该家庭下的全部设备,后续新绑定的设备也自动可见。适用于家人共用。
·设备分享:被分享用户只获得指定单台设备的使用权,不进入家庭,也看不到家庭内的其他设备。适用于临时授权给外部人员。
被分享的设备不出现在 getDeviceList 的结果中,必须通过 getDeviceListSharedWithMe 查询。
九、解绑设备后,之前分享出去的用户还能访问吗?
不能。设备解绑意味着它从该家庭中被移除,依附于这台设备的分享关系随之失效。若需要将设备迁移到另一个家庭,请先解绑,再用新的设备绑定签名绑定到目标家庭,绑定完成后需重新创建分享 Token 并让对方重新接收。
十、被分享用户能对设备做哪些操作?
被分享用户获得的是该台设备的使用权,可以拉流监控、发起通话、下发控制命令;但不具备管理权:无法解绑设备、无法修改设备别名与房间归属、无法再把该设备转分享给第三方,也看不到设备所属家庭内的其他设备。
十一、同一台设备可以分享给多少个用户?
getDeviceSharedUsers 单次最多返回 100 条共享用户记录且不支持分页,因此建议在产品侧把单台设备的共享用户数控制在 100 以内,避免列表展示不全。
十二、接口参考
这篇涉及接口的完整定义参见:
·TXIoTDeviceManager(Android)
·TXIoTDeviceManager(iOS)
·TXIoTDeviceManager(小程序)
·TXIoTDeviceManager(鸿蒙)
·TXIoTEngineDef(数据结构与错误码)
设备的绑定与解绑参见 设备绑定,家庭成员与房间的管理参见 家庭管理。接收到共享设备后,可继续接入 远程控制。