检测 AVAudioSession 被“降低音量”

17

我正在开发一款播客应用程序。该应用程序使用AVAudioSessionCategoryPlayback会话类型来播放音频。它几乎可以满足我的所有要求,可以暂停其他播放的音乐,当有电话来时被打断并且通常按我的意愿正常运行。但有一个例外情况:当播放更高优先级的音频时(例如运行转向导航应用程序时),我的应用程序中的音频会被降低音量但仍然继续播放。这会产生不希望的两个声音混合在一起的声音效果。我希望我的应用程序中的音频在覆盖声音时暂停,然后在其完成后再次播放。

我尝试更改不同的AVAudioSession属性,例如AVAudioSessionCategoryOptionMixWithOthers,但这些只会改变较低优先级声音与我的应用程序混合的方式。它们不能改变我的应用程序如何与更高优先级的声音混合。我还尝试观察sharedSessionotherAudioPlaying属性,但当这些短片段叠加时,它没有触发更改。

是否有任何方法可以检测何时降低我的应用程序中的音频,以便我可以暂停它?或者防止我的应用程序的音频被降低,使其将这些其他声音视为打断?

谢谢。


你尝试过使用 kAudioSessionBeginInterruptionkAudioSessionEndInterruption 吗? - iwasrobbed
是的,但叠加淡出在 AVAudioSession 方面并不算作“中断”。因此,这些回调/通知不会被触发。 - David Smith
2
如果你认为应该这样做的话,你可以向苹果提交一个雷达反馈。在我看来,它似乎应该被视为音频会话中断。 - iwasrobbed
你有解决这个问题吗?我也遇到了同样的困扰,请告诉我是否已经找到解决方案。 - Sunil_Vaishnav
问题可能是,一旦您收到了“ducking”通知并停止了声音,您的应用程序就会停止运行,因此您无法观察到“unducking”通知。系统需要显式支持,但由于似乎没有这样的支持,我认为目前没有办法做到这一点。我发起了一个支持事件,以从苹果那里获得答案。 - Martin Hering
我已经提供了以下解决方案,需要iOS 9。 - tmoore
6个回答

5

是的,这是正确的答案,应该明确地点赞! - Thread Pitt

1
我向 Apple DTS 报告了这个问题。以下是他们回复的内容:
感谢您联系苹果开发技术支持(DTS)。我们的工程师已经审查了您的请求,并得出结论,鉴于当前正在使用的系统配置,没有受支持的方法来实现所需的功能。
如果您希望苹果在将来考虑添加支持,以允许/通知后台应用程序在前台应用程序选择淡化其他音频时停止播放音频,然后在淡化完成后启动音频,请通过 Bug Reporter 工具提交增强请求http://bugreport.apple.com
很遗憾,目前似乎无法实现。

0
在你的 AppDelegate.m 类中,在 didFinishLaunchingWithOptions 函数中,监听以下通知。
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioSessionInterruption:) name:AVAudioSessionInterruptionNotification object:nil];

在应用程序启动方法之外,将选择器实现为

- (void)audioSessionInterruption:(NSNotification *)notif{
    NSLog(@"\n\nInterruption Notification :%@\n\n",notif.userInfo);
}

希望这对你有用...

0
你可能需要研究中断,并在中断时简单地丢弃音频会话,然后在中断结束时恢复它,如下所示:
在你的ViewDidLoad中:
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];

if ([self canBecomeFirstResponder]) {
    [self becomeFirstResponder];
}

处理通知:

static NSInteger audioSessionActiveCounter = 0;

- (void)audioSessionDidChangeInterruptionType:(NSNotification *)notification
{
    AVAudioSessionInterruptionType interruptionType = [[[notification userInfo] objectForKey:AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];

    if (AVAudioSessionInterruptionTypeBegan == interruptionType)
    {
       DDLogVerbose(@"Session interrupted: --- Begin Interruption ---");
       // stop your session here with a setActive:NO

    }
    else if (AVAudioSessionInterruptionTypeEnded == interruptionType)
    {
        DDLogVerbose(@"Session interrupted: --- End Interruption ---");
       // resume your session here with a setActive:YES
    }
}

希望它有所帮助。

0

我从未这样做过,但我想你可以使用AudioSession服务的C函数audioSessionAddPropertyListener来注册kAudioSessionProperty_OtherAudioIsPlaying的回调函数。

请注意,“FLATDACTED”文档和苹果开发者论坛中存在一些混淆,关于所有或某些AudioSession C函数在“将来”可能会被弃用。


谢谢你的建议,我很感激帮助。然而,我已经尝试过使用Obj-C和C API了,但都没有产生所需的回调结果,当在ducking期间被触发时。 - David Smith

0

我不相信kAudioSessionProperty_OtherAudioIsPlaying会以任何方式回调 - 可能你需要定期轮询这个值。

当设备上正在播放其他音频时,它应该返回一个非零值。这可能并不表示您被"压低"了,但它会表明其他音频正在与您的音频混合。据说,只有当另一个应用程序设置了其音频会话的kAudioSessionProperty_OtherMixableAudioShouldDuck属性时,才会压低您的音频。

关于轮询 - 是的,它可能不像回调那样优雅,但有时是必要的,我怀疑轮询此值只是微小的开销。

希望这可以帮到您。


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