ios - 应用程序在后台录制时连接蓝牙耳机会导致录制停止
问题描述
我面临以下问题,希望其他人遇到它并可以提供解决方案:
- 我
AVAudioEngine
用来访问麦克风。在 iOS 12.4 之前,每次音频路由更改时,我都能够重新启动AVAudioEngine
图表以重新配置它并确保输入/输出音频格式适合新的输入/输出路由。由于 iOS 12.4 中引入的更改,不再可能AVAudioEngine
在应用程序处于后台时启动(或重新启动)图表(除非它是在中断之后)。
当我尝试这样做时,Apple 现在抛出的错误是:
2019-10-03 18:34:25.702143+0200 [1703:129720] [aurioc] 1590: AUIOClient_StartIO failed (561145187)
2019-10-03 18:34:25.702528+0200 [1703:129720] [avae] AVAEInternal.h:109 [AVAudioEngineGraph.mm:1544:Start: (err = PerformCommand(*ioNode, kAUStartIO, NULL, 0)): error 561145187
2019-10-03 18:34:25.711668+0200 [1703:129720] [Error] Unable to start audio engine The operation couldn’t be completed. (com.apple.coreaudio.avfaudio error 561145187.)
我猜苹果在那里关闭了一个安全漏洞。所以现在我删除了当音频路由改变时重新启动图形的代码(例如连接蓝牙耳机)。
- 似乎当 I/O 音频格式发生变化时(就像用户连接蓝牙设备时发生的那样),
.AVAudioEngingeConfigurationChange
会触发一个通知,以允许集成应用程序对格式的变化做出反应。这确实是我从一开始就应该用来处理 I/O 格式的更改,而不是强制重新启动图形。根据 Apple 文档 - “当音频引擎的 I/O 单元观察到音频输入或输出硬件的通道数或采样率发生变化时,音频引擎会停止、取消初始化并发出此通知。” (请参阅此处的文档)。当应用程序在后台运行时发生这种情况时,由于第 1 点,我无法使用正确的音频 i/o 格式启动音频引擎。
因此,最重要的是,通过关闭一个安全漏洞,Apple 引入了一个错误,即在应用程序处于后台时对音频 I/O 格式更改做出反应。还是我错过了什么?
我附上了一个代码片段来更好地描述这个问题。对于即插即用的 AppDelegate,请参见此处 - https://gist.github.com/nevosegal/5669ae8fb6f3fba44505543e43b5d54b。
class RCAudioEngine {
private let audioEngine = AVAudioEngine()
init() {
setup()
start()
NotificationCenter.default.addObserver(self, selector: #selector(handleConfigurationChange), name: .AVAudioEngineConfigurationChange, object: nil)
}
@objc func handleConfigurationChange() {
//attempt to call start()
//or to audioEngine.reset(), setup() and start()
//or any other combination that involves starting the audioEngine
//results in an error 561145187.
//Not calling start() doesn't return this error, but also doesn't restart
//the recording.
}
public func setup() {
//Setup nodes
let inputNode = audioEngine.inputNode
let inputFormat = inputNode.inputFormat(forBus: 0)
let mainMixerNode = audioEngine.mainMixerNode
//Mute output to avoid feedback
mainMixerNode.outputVolume = 0.0
inputNode.installTap(onBus: 0, bufferSize: 4096, format: inputFormat) { (buffer, _) -> Void in
//Do audio conversion and use buffers
}
}
public func start() {
RCLog.debug("Starting audio engine")
guard !audioEngine.isRunning else {
RCLog.debug("Audio Engine is already running")
return
}
do {
audioEngine.prepare()
try audioEngine.start()
} catch {
RCLog.error("Unable to start audio engine \(error.localizedDescription)")
}
}
}
解决方案
我只看到 iOS 12.4 中的修复。我不确定这是否会导致问题。
随着发行说明https://developer.apple.com/documentation/ios_ipados_release_notes/ios_12_4_release_notes
“解决了在 iOS 12.2 或更高版本中在 Leaks 工具下运行应用程序导致在给定运行中的第一次泄漏检查之后随机数的误报泄漏的问题。您可能仍会在模拟器中或在使用 Xcode 10.2 及更高版本的 Instruments 时的 macOS 应用程序。(48549361)"
如果您是已签名的开发人员,您可以向 Apple 提出问题。如果缺陷在于他们,他们可能会帮助您。
您还可以使用即将发布的 iOS 版本进行测试,以检查您的代码在未来版本中是否有效(使用 Apple beta 程序)
推荐阅读
- java - 将 ProcessBuilder 命令翻译成 Linux 可以理解的东西
- database - 续集。错误:“createdAt”列中的空值违反非空约束
- azure-devops - auth 后面的新 VSTS 构建徽章 URL 不适合 Github 存储库
- c - Linux C,如何安排 10 个等待线程在 FIFO 中执行?
- php - 在 woocommerce 自定义电子邮件通知中获取 ACF 自定义字段值
- office-store - 应用状态停留在“初始扫描”一个多月
- dart - TextFormField Flutter 未适当更改
- swift - 项目不知道彼此并在云中按属性排序的有序列表:当用户重新排序时如何避免云中的索引更改?
- arrays - 在反应中使用 axios.get 渲染嵌套的 json 数据
- sql - Disabled Trigger Re-Enabled After ALTER .. 怎么回事?