kAudioDevicePropertyDeviceIsRunningSomewhere针对AirPods等设备返回值异常求助
解决AirPods等无线音频设备kAudioDevicePropertyDeviceIsRunningSomewhere返回值异常问题
针对AirPods这类无线音频设备,kAudioDevicePropertyDeviceIsRunningSomewhere属性存在已知兼容性问题:设备处于活跃使用状态时,该属性始终返回0(而非预期的1);即便添加ListenerBlock能触发回调,返回值依然不符合实际状态。
以下是几个可靠的替代方案:
1. 结合流配置与采样率判断设备状态
无线设备活跃时,其音频流配置和采样率会发生明显变化:
- 查询
kAudioDevicePropertyStreamConfiguration,检查输入/输出流的数量是否大于0; - 查询
kAudioDevicePropertyNominalSampleRate,确认采样率是否切换到实际工作值(如44100Hz、48000Hz),而非默认的0或极低数值。
示例代码片段:
UInt32 propSize = 0; AudioObjectPropertyAddress streamConfigAddr = { kAudioDevicePropertyStreamConfiguration, kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMain }; // 先获取属性大小 AudioObjectGetPropertyDataSize(deviceID, &streamConfigAddr, 0, NULL, &propSize); AudioBufferList* bufferList = malloc(propSize); AudioObjectGetPropertyData(deviceID, &streamConfigAddr, 0, NULL, &propSize, bufferList); // 检查输出流数量 BOOL hasActiveStream = (bufferList->mNumberBuffers > 0); free(bufferList); // 检查采样率 Float64 sampleRate = 0; propSize = sizeof(Float64); AudioObjectPropertyAddress sampleRateAddr = { kAudioDevicePropertyNominalSampleRate, kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMain }; AudioObjectGetPropertyData(deviceID, &sampleRateAddr, 0, NULL, &propSize, &sampleRate); BOOL isSampleRateActive = (sampleRate >= 44100.0);
2. 监听系统音频路由变化
借助AVAudioSession的路由变更通知,结合当前路由的设备信息判断状态:
- 监听
AVAudioSessionRouteChangeNotification; - 在回调中解析
AVAudioSessionRouteDescription,检查输出/输入端口是否为目标无线设备,且端口处于活跃状态。
示例代码片段:
[[NSNotificationCenter defaultCenter] addObserverForName:AVAudioSessionRouteChangeNotification object:[AVAudioSession sharedInstance] queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { AVAudioSessionRouteDescription* currentRoute = [[AVAudioSession sharedInstance] currentRoute]; for (AVAudioSessionPortDescription* port in currentRoute.outputs) { if ([port.portType isEqualToString:AVAudioSessionPortBluetoothA2DP] || [port.portType isEqualToString:AVAudioSessionPortBluetoothHFP]) { // AirPods等蓝牙设备处于活跃输出状态 BOOL isDeviceActive = YES; // 执行后续逻辑 break; } } }];
3. 查询设备活跃IO客户端数量
使用kAudioDevicePropertyIOClientCount属性直接获取当前使用设备的客户端数量,该属性在无线设备上的表现更稳定:
- 当客户端数量大于0时,说明设备处于活跃使用状态。
示例代码片段:
UInt32 clientCount = 0; UInt32 propSize = sizeof(UInt32); AudioObjectPropertyAddress clientCountAddr = { kAudioDevicePropertyIOClientCount, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMain }; OSStatus status = AudioObjectGetPropertyData(deviceID, &clientCountAddr, 0, NULL, &propSize, &clientCount); if (status == noErr && clientCount > 0) { // 设备处于活跃状态 }
补充说明
出现"监听触发但值异常"的现象,是因为Core Audio对无线设备的状态变更通知逻辑与属性更新不同步:设备状态变化会触发ListenerBlock,但kAudioDevicePropertyDeviceIsRunningSomewhere的内部更新存在逻辑滞后或错误,因此完全依赖该属性不可靠,建议结合上述方案交叉验证。
内容的提问来源于stack exchange,提问作者espc
相关产品推荐
相关产品推荐

