获取设备详情
读取 AIBuds 设备当前可用的信息。设备详情以设备对象属性的形式公开;SDK 不提供单一的 getDeviceDetails 请求或 DeviceDetails 结果模型。
通过 DeviceConvertible 读取标识、固件、连接和广播信息。如果设备同时符合 DeviceInfoAPI,还可读取电池状态、设备能力、硬件配置、语言设置、通话状态、存储信息和媒体数量。
前置条件
读取设备详情前:
- 从扫描、已保存设备或连接流程中获取
DeviceConvertible实例。 - 需要设备最新上报值时,请等待设备进入已连接且就绪状态。
- 在 SDK 或设备提供可选属性前,应将其视为不可用。
:::info 当前快照 读取这些属性不会发送蓝牙命令。这些值表示 SDK 的当前快照,可能来自发现数据、持久化设备数据或活动连接期间收到的信息。 :::
API 参考
框架
AIBuds.xcframework
导入
在需要使用 SDK 的文件中导入主框架:
- Swift
- Objective-C
import AIBuds#import <AIBuds/AIBuds-Swift.h>
#import <AIBuds/AIBuds.h>协议
设备详情由两个协议公开。DeviceConvertible 提供基础设备快照;连接设备支持 DeviceInfoAPI 时,该协议提供更多设备信息属性。
- Swift
- Objective-C
/// Defines the persistent identity and capabilities of an AIBuds device.
protocol DeviceConvertible: NSObjectProtocol, NSSecureCoding
/// The protocol for device information related API.
protocol DeviceInfoAPI: DeviceAPI/// Defines the persistent identity and capabilities of an AIBuds device.
@protocol AIBudsDeviceConvertible <NSSecureCoding, NSObject>
/// The protocol for device information related API.
@protocol AIBudsDeviceInfoAPI <AIBudsDeviceAPI>属性
基础设备属性
以下属性由 DeviceConvertible 提供。
| 类别 | 属性 | 说明 |
|---|---|---|
| 标识 | name, uuid, bluetoothName, macAddress, product | SDK 当前已知的设备名称和标识符。 |
| 硬件 | deviceModel, deviceSerialNum, formatedProjNumber | 受支持设备上报的可选值。 |
| 固件 | firmwareVersion, formatedFirmwareVersion, coProcessorFirmwareVersion | formatedFirmwareVersion 是 Demo 用于界面显示的主固件版本字符串。 |
| 连接 | connectionState, deviceState, isConnectedAndReady, isBusy, lastConnectTime | 依赖实时设备状态前,请检查 isConnectedAndReady。 |
| 绑定 | bindUserId, userBindTime, isAlreadyUnbind, shouldAutoReconnectWhenAppLaunch | SDK 维护的绑定和重连状态。 |
| 广播 | advertisementDataString, advertisementRawData, manufacturerData, manufacturerHexDataString, timestampOfAdvertisementData | 从最近一次收到的广播数据中派生的值。 |
| 展示 | thumbnail, screenName, customContent | 宿主 App UI 可使用的可选值。 |
设备信息属性
确认设备支持 DeviceInfoAPI 后,可以读取以下扩展快照值。
| 属性 | 类型 | 描述 |
|---|---|---|
batteryStatusInfo | BatteryStatusModel? | 设备各电池组件的实时信息。 |
deviceCapabilities | DeviceCapabilities? | 设备上报的标准化功能标志;收到有效能力信息前为 nil。 |
hardwareConfiguration | DeviceHardwareConfiguration | 设备上报的物理输入硬件和设备端引导要求。 |
languageSetting | DeviceLanguage | 设备当前语言。 |
supportedLanguages | [NSNumber] | 设备支持的 DeviceLanguage 原始值。 |
callStatus | CallStatus | 当前通话状态。 |
storageInfo | StorageInfoModel? | 以 MB 为单位的已用和可用存储空间。 |
mediaCountInfo | MediaCountInfoModel? | 照片、视频和音频文件数量。 |
isSupportAdjustRecordDuration | Bool | 是否支持配置最大录音时长。 |
aiSolutionCapabilities | AIBudsAISolutionCapabilities | 设备上报的 AI 能力。 |
coprocessorModel | CoprocessorModel | 设备协处理器型号。 |
imageEnhancementPostProcessingAlgorithm | ImageEnhancementPostProcessingAlgorithm | 设备当前上报的图像增强后处理算法;默认为 .general。 |
recommendedMaxVideoRecordingDurationOptions | [NSNumber] | 设备建议的视频最大录制时长档位(分钟);默认为 [1, 3, 9, 12]。 |
recommendedMaxAudioRecordingDurationOptions | [NSNumber] | 设备建议的音频最大录制时长档位(分钟);默认为 [30, 60, 120]。 |
minimumBatteryLevelForMediaOperations | Int | 照片、视频、音频和文件传输所需的最低电量百分比;默认为 30。OTA 使用独立规则。 |
常见状态值
batteryStatusInfo 可能包含产品支持的任意电池组件:
BatteryComponent | 含义 |
|---|---|
.glass | 眼镜主体 |
.leftEarbud / .rightEarbud | 左耳机或右耳机 |
.chargingCase | 充电盒 |
.mainSpeaker / .sideSpeaker | 主扬声器或侧扬声器 |
.headphones | 头戴式耳机 |
.unknown | 组件不可用或无法识别 |
使用 deviceCapabilities 中的字段判断是否开放 TWS、空间音频、多点连接、ANC、设备端语音助手、低音引擎、直播流、喜马拉雅或工厂测试啁啾提示音。不要仅根据 product 推断这些功能。值为 nil 表示 SDK 尚未收到有效能力信息,并不表示所有功能都不受支持。
hardwareConfiguration 描述产品的操作方式:
| 属性 | 含义 |
|---|---|
hasTouchInput | 设备配备触摸输入区域。 |
hasPhysicalButtonInput | 设备配备物理按键输入。 |
requiresOnDeviceVoiceAssistantGuidance | 宿主 App 应提供设备端语音助手的使用引导。 |
callStatus 使用 CallStatus:
| 值 | 含义 |
|---|---|
.notInCall | 当前没有通话。 |
.ringing | 来电正在响铃。 |
.inCall | 当前正在通话。 |
.threeWayRinging | 支持时,表示三方通话正在响铃。 |
.aiChat | 设备将 AI 对话报告为当前通话通道活动。 |
.unknown | 通话状态不可用或无法识别。 |
使用示例
读取设备详情
以下示例采用 SDK Demo 中 DeviceInfoDetailsController 的处理方式:先读取基础设备属性,再按协议支持情况加入 DeviceInfoAPI 属性。
- Swift
- Objective-C
import AIBuds
typealias DeviceDetail = (label: String, value: String)
func formattedDate(_ date: Date?, unavailable: String) -> String {
guard let date else { return unavailable }
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .medium
return formatter.string(from: date)
}
func deviceDetails(for device: DeviceConvertible) -> [DeviceDetail] {
let unavailable = "N/A"
var details: [DeviceDetail] = [
("Device Name", device.name),
("UUID", device.uuid.uuidString),
("Bluetooth Name", device.bluetoothName ?? unavailable),
("MAC Address", device.macAddress ?? unavailable),
("Product", String(describing: device.product)),
("Device Model", device.deviceModel ?? unavailable),
("Serial Number", device.deviceSerialNum ?? unavailable),
("Firmware Version", device.formatedFirmwareVersion ?? unavailable),
("Co-processor Firmware", device.coProcessorFirmwareVersion ?? unavailable),
("Project Number", device.formatedProjNumber ?? unavailable),
("Last Connection", formattedDate(device.lastConnectTime, unavailable: unavailable)),
("Auto Reconnect", device.shouldAutoReconnectWhenAppLaunch ? "Yes" : "No"),
("Advertisement Data", device.advertisementDataString ?? unavailable),
("Manufacturer Data", device.manufacturerHexDataString ?? unavailable),
(
"Advertisement Timestamp",
formattedDate(device.timestampOfAdvertisementData, unavailable: unavailable)
),
("Screen Name", device.screenName ?? unavailable),
("Custom Content", device.customContent ?? unavailable),
]
guard let info = device as? DeviceInfoAPI else {
return details
}
let supportedLanguages = info.supportedLanguages
.compactMap { DeviceLanguage(rawValue: $0.intValue) }
.map { String(describing: $0) }
.joined(separator: ", ")
details.append(contentsOf: [
("Battery Status", info.batteryStatusInfo?.description ?? unavailable),
("Device Capabilities", info.deviceCapabilities?.description ?? unavailable),
("Hardware Configuration", info.hardwareConfiguration.description),
("Language", String(describing: info.languageSetting)),
("Supported Languages", supportedLanguages.isEmpty ? unavailable : supportedLanguages),
("Call Status", String(describing: info.callStatus)),
("Storage", info.storageInfo?.description ?? unavailable),
("Media Count", info.mediaCountInfo?.description ?? unavailable),
("Adjustable Recording Duration", info.isSupportAdjustRecordDuration ? "Yes" : "No"),
("AI Capabilities", String(describing: info.aiSolutionCapabilities)),
("Co-processor Model", String(describing: info.coprocessorModel)),
(
"Image Enhancement",
String(describing: info.imageEnhancementPostProcessingAlgorithm)
),
("Recommended Video Duration Options", info.recommendedMaxVideoRecordingDurationOptions.description),
("Recommended Audio Duration Options", info.recommendedMaxAudioRecordingDurationOptions.description),
("Minimum Media Battery", "\(info.minimumBatteryLevelForMediaOperations)%"),
])
return details
}#import <AIBuds/AIBuds-Swift.h>
#import <AIBuds/AIBuds.h>
- (NSArray<NSDictionary<NSString *, NSString *> *> *)deviceDetailsForDevice:
(id<AIBudsDeviceConvertible>)device {
NSString *unavailable = @"N/A";
NSMutableArray<NSDictionary<NSString *, NSString *> *> *details = [NSMutableArray array];
void (^addDetail)(NSString *, id _Nullable) = ^(NSString *label, id _Nullable value) {
[details addObject:@{
@"label" : label,
@"value" : value ? [value description] : unavailable,
}];
};
addDetail(@"Device Name", device.name);
addDetail(@"UUID", device.uuid.UUIDString);
addDetail(@"Bluetooth Name", device.bluetoothName);
addDetail(@"MAC Address", device.macAddress);
addDetail(@"Product", @(device.product));
addDetail(@"Device Model", device.deviceModel);
addDetail(@"Serial Number", device.deviceSerialNum);
addDetail(@"Firmware Version", device.formatedFirmwareVersion);
addDetail(@"Co-processor Firmware", device.coProcessorFirmwareVersion);
addDetail(@"Project Number", device.formatedProjNumber);
addDetail(@"Last Connection", device.lastConnectTime);
addDetail(@"Auto Reconnect", device.shouldAutoReconnectWhenAppLaunch ? @"Yes" : @"No");
addDetail(@"Advertisement Data", device.advertisementDataString);
addDetail(@"Manufacturer Data", device.manufacturerHexDataString);
addDetail(@"Advertisement Timestamp", device.timestampOfAdvertisementData);
addDetail(@"Screen Name", device.screenName);
addDetail(@"Custom Content", device.customContent);
id<AIBudsDeviceInfoAPI> info = (id<AIBudsDeviceInfoAPI>)device;
if ([info conformsToProtocol:@protocol(AIBudsDeviceInfoAPI)]) {
addDetail(@"Battery Status", info.batteryStatusInfo);
addDetail(@"Device Capabilities", info.deviceCapabilities);
addDetail(@"Hardware Configuration", info.hardwareConfiguration);
addDetail(@"Language", @(info.languageSetting));
addDetail(@"Supported Languages", info.supportedLanguages);
addDetail(@"Call Status", @(info.callStatus));
addDetail(@"Storage", info.storageInfo);
addDetail(@"Media Count", info.mediaCountInfo);
addDetail(@"Adjustable Recording Duration",
info.isSupportAdjustRecordDuration ? @"Yes" : @"No");
addDetail(@"AI Capabilities", @(info.aiSolutionCapabilities));
addDetail(@"Co-processor Model", @(info.coprocessorModel));
addDetail(@"Image Enhancement", @(info.imageEnhancementPostProcessingAlgorithm));
addDetail(@"Recommended Video Duration Options", info.recommendedMaxVideoRecordingDurationOptions);
addDetail(@"Recommended Audio Duration Options", info.recommendedMaxAudioRecordingDurationOptions);
addDetail(@"Minimum Media Battery",
[NSString stringWithFormat:@"%ld%%",
(long)info.minimumBatteryLevelForMediaOperations]);
}
return details;
}请使用应用自己的视图模型和本地化方案渲染返回的数据行。Demo 使用表格视图,并将枚举值转换为本地化显示文本。
刷新存储或媒体信息
storageInfo 和 mediaCountInfo 是快照属性。如果界面需要最新值,请先请求更新,并在操作成功后读取对应属性。
- Swift
- Objective-C
guard let info = device as? DeviceInfoAPI else { return }
info.requestQueryStorageInfo { success, error in
guard success else {
print(error?.localizedDescription ?? "Storage query failed")
return
}
print(info.storageInfo?.description ?? "Storage information is unavailable")
}id<AIBudsDeviceInfoAPI> info = (id<AIBudsDeviceInfoAPI>)self.device;
if ([info conformsToProtocol:@protocol(AIBudsDeviceInfoAPI)]) {
[info requestQueryStorageInfoWithCompletion:^(BOOL success, NSError *_Nullable error) {
if (!success) {
NSLog(@"Storage query failed: %@", error.localizedDescription);
return;
}
NSLog(@"%@", info.storageInfo);
}];
}Swift 调用 requestQueryMediaCountInfo(_:),Objective-C 调用 requestQueryMediaCountInfoWithCompletion:,以便在需要时刷新 mediaCountInfo。
错误处理
读取属性本身不会返回异步错误。显式刷新操作通过完成回调报告失败。处理不可用信息时:
- 需要实时值时检查
device.isConnectedAndReady。 - 读取
DeviceInfoAPI属性前确认设备支持该协议。 - 正确处理可选属性,不要假设所有设备型号都会上报每个值;应将
nil的deviceCapabilities值视为未知,而不是不支持。 - 将广播字段视为最近一次收到的广播快照。
- 对存储或媒体数量查询等显式刷新操作处理
success和error。
最佳实践
-
检查协议支持:读取扩展属性前确认设备支持
DeviceInfoAPI。 -
按上报值开放功能:优先使用
deviceCapabilities中的标准化标志、建议录制时长数组和minimumBatteryLevelForMediaOperations,不要依赖产品名称或硬编码限制。 -
将值视为快照:不要假设所有属性在同一时间刷新。
-
处理可选值:显示不可用状态,不要编造回退设备数据。
-
按需刷新:界面需要当前值时,再调用存储和媒体数量查询方法。
-
本地化显示值:将产品、语言、通话状态等枚举转换为面向用户的本地化文本。
注意事项
- 设备能力和可用字段因产品与固件而异。
DeviceProduct.headphones标识头戴式耳机产品,BatteryComponent.headphones标识其电池条目。 supportedLanguages包含NSNumber值,这些值映射到DeviceLanguage.rawValue。StorageInfoModel提供usedSpaceInMB和freeSpaceInMB。MediaCountInfoModel提供photoCount、videoCount和audioCount。- UI 需要单独字段时,应优先读取模型属性,不要解析
description。