【问题标题】:iOS AVAudioSession interruption notification not working as expectediOS AVAudioSession 中断通知未按预期工作
【发布时间】:2015-10-26 16:09:58
【问题描述】:

我想知道我的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 通知?

【问题讨论】:

  • 此链接可能对您有所帮助:- stackoverflow.com/questions/23586056/…
  • 来自苹果文档:“不能保证开始中断一定会有结束中断。您的应用需要注意切换到前台运行状态或用户按下播放按钮。在无论哪种情况,请确定您的应用是否应重新激活其音频会话。”

标签: ios avfoundation interrupt avaudiorecorder avaudiosession


【解决方案1】:

这是一个普遍存在的问题,影响任何使用 AV 框架组件的应用程序(对于原生 iOS 应用程序也是如此)。

正如's documentation 中关于音频中断主题的解释,InterruptionTypeEnded 实际上应该应用于上述场景:

如果用户解除中断……系统调用你的回调方法,表示中断已经结束。

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

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

因此,在提到的场景中需要一种不同的方法。


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

处理媒体中断确切问题的一种方法是听MPMusicPlayerControllerplaybackState,如以下stackoverflow 问题所示:Detecting if music is playing?


处理中断问题的更直接的方法是:

通过在InterruptionTypeBegan 时重新调用您的音频组件来完全阻止外部音频中断。

或通过向 UI 指示外部媒体源已中断音频会话(例如显示不活动的麦克风)。


希望  会想出一个更好的解决方案,但同时这应该为您提供一些解决中断问题的选项。

【讨论】:

  • 感谢@Aleksander Azizi!顺便说一句,您能否详细解释一下“通过在 InterruptionTypeBegan 时重新调用您的音频组件来完全阻止外部音频中断”。 ?
  • @nahung89 一旦InterruptionTypeBegan 被调用,您可以再次初始化音频引擎。有效地阻止任何其他音频源。
  • 我明白了。其实我之前尝试过,但没有奏效。电话/警报/提醒...在音频会话中始终具有更高的优先级。在我们重新设置音频播放器后,它会立即停止。
  • 我发现 .play() 不能在中断处理程序中调用,因为这会阻止调用 audioPlayerEndInterruption。 .play() 必须仅在 audioPlayerEndInterruption() 中调用才能使恢复工作。请在此处查看我的对话以获取详细信息stackoverflow.com/a/38800403/1827488
  • 另一种解决方法是收听路由更改通知。如果您有不匹配的 BeginInterruption 和 Route Changes,您可以尝试重新启动。
【解决方案2】:

如果您还没有,请尝试将您的AVCaptureSession 的属性usesApplicationAudioSession 设置为NO

This问答可以作为一个很好的参考,如果你正在寻找更多的细节。

【讨论】:

  • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接的答案可能会失效。
  • 感谢您的反馈@LeftyX 我没有考虑您的顾虑,从现在开始我的回答中会考虑到这一点。我对为什么我的回复被否决感到有些困惑,因为它确实包含了一个可行的解决方案。
  • 我没有投反对票。我几乎不反对答案。最好在回答中给出完整的解释。
  • @LeftyX 我并不是要暗示你有。再次感谢,从现在开始,我一定会在我的回复中包含详细的解释。
【解决方案3】:

我尝试这个并发现 InterruptionTypeEnded 可能会在某些应用中的音乐暂停后调用,但在暂停时不会调用其他的。

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

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

【讨论】:

    猜你喜欢
    • 2022-01-03
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多