iOS AVAudioSession中断通知不按预期工作

20

我想知道何时我的AVAudioRecorder无法访问(例如在播放音乐时)。

由于audioRecorderEndInterruption将在iOS 9中被弃用,因此我正在关注AVAudioSession的中断通知(但两者都没有按预期工作)。

问题在于,如果应用程序在发生中断时处于前台并继续保持在前台,则不会调用中断通知。

例如:用户启动和停止播放音乐,而不将应用程序移至后台。

为了检测任何中断,我正在使用:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioSessionWasInterrupted:) name:AVAudioSessionInterruptionNotification object:nil];
...
- (void)audioSessionWasInterrupted:(NSNotification *)notification {
    if ([notification.name isEqualToString:AVAudioSessionInterruptionNotification]) {
        NSLog(@"Interruption notification");

        if ([[notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey] isEqualToNumber:[NSNumber numberWithInt:AVAudioSessionInterruptionTypeBegan]]) {
            NSLog(@"InterruptionTypeBegan");
        } else {
            NSLog(@"InterruptionTypeEnded");
        }
    }
}

我得到了预期的InterruptionTypeBegan,但是如果应用程序仍在前台,则不会调用InterruptionTypeEnded(这意味着它只有在将应用程序放入后台并重新回到前台后才会被调用)。

当应用程序在前台发生中断时,我该如何接收InterruptionTypeEnded通知?


这个链接可能会对你有所帮助:https://dev59.com/O3_aa4cB1Zd3GeqP45Fy - Bharat Nakum
5
来自苹果文档:“开始中断可能没有结束中断的保证。您的应用程序需要注意切换到前台运行状态或用户按下播放按钮。在任一情况下,请确定您的应用程序是否应该重新激活其音频会话。” - Fennelouski
3个回答

10
这是一个普遍存在的问题,影响使用 AV 框架组件的任何应用程序(原生 iOS 应用程序也是如此)。
文档 中关于音频中断的说明所述,实际上应该在提到的情况下应用 InterruptionTypeEnded

如果用户关闭中断...系统将调用您的回调方法,指示中断已结束。

然而,它还指出,InterruptionTypeEnded 可能根本不会被调用:

没有保证开始中断一定会有结束中断。

因此,在提到的情况下需要采用不同的方法。

当涉及到处理音乐中断时,这个问题不会再存在太长时间。iOS 9有效地防止在调用应用程序的音频处理程序时使用外部音频源。

处理媒体中断的确切方法可能是监听MPMusicPlayerControllerplaybackState,如此stackoverflow问题所示:检测是否正在播放音乐?


一个更为直接的处理打扰问题的方式是要么:
在InterruptionTypeBegan时重新调用您的音频组件,完全阻止外部音频干扰。
或者通过提供UI指示表明外部媒体源已中断音频会话(例如显示非活动麦克风)。

希望能够提出更好的解决方案来解决这个问题,但在此期间,这将为您提供一些解决中断问题的选项。


感谢@Aleksander Azizi!顺便问一下,能否详细解释一下“在中断类型开始时通过重新调用音频组件来完全阻止外部音频干扰”? - nahung89
@nahung89 一旦调用了 InterruptionTypeBegan,您可以再次初始化音频引擎。有效地阻止任何其他音频源。 - Aleksander Azizi
我知道了。实际上我之前尝试过,但没有成功。电话、闹钟、提醒等在音频会话中始终拥有更高的优先级。一旦我们重新设置音频播放器,它就会立即停止。 - nahung89
我发现在中断处理程序中无法调用.play(),因为这会阻止调用audioPlayerEndInterruption。.play()必须仅在audioPlayerEndInterruption()内调用,以使恢复工作。有关详细信息,请查看我的对话http://stackoverflow.com/a/38800403/1827488。 - rockhammer
1
另一个解决方法是监听路由更改通知。如果您有不匹配的BeginInterruption和Route Changes,可以尝试重新启动。 - yano

-1
如果您还没有这样做,请尝试将AVCaptureSession的属性usesApplicationAudioSession设置为NO
如果您需要更多细节,问题和答案可能会作为一个很好的参考。

1
虽然这个链接可能回答了问题,但最好在此处包含答案的基本部分并提供参考链接。如果链接页面更改,仅有链接的答案可能会失效。 - LeftyX
谢谢您的反馈@LeftyX。我没有考虑到您的顾虑,从现在起我会在我的回答中考虑到这一点。然而,我有些困惑为什么我的回答会被投票踩,因为它确实包含了一个可行的解决方案。 - ChrisHaze
我没有点踩。我很少会对回答进行点踩。在你的回答中给出完整的解释总是更好的选择。 - LeftyX
@LeftyX,我并不是想暗示你有这样做。再次感谢你,我会确保从现在开始在我的回复中包含详细的解释。 - ChrisHaze

-1

我尝试了一下,发现在某些应用程序中,当音乐暂停时,可能会调用InterruptionTypeEnded,但在其他应用程序中不会调用。

我的解决方案是更新UI以让用户知道记录已停止,并进行一些相关工作,例如文件操作。当中断结束时,激活AVAudioSession,如果没有错误,则开始新的记录。

如果您想在中断前后加入文件,则此问题的答案:AVAudioRecorder records only the audio after interruption 可能对您有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接