检测环/静音开关位置变化

我正在开发一个我想要的应用程序:

  1. 在播放音频时尊重铃声/静音开关,和

  2. 当铃声/静音开关设置为静音时,显示一个图标,表示声音已静音。

要求1很简单:我使用AVAudioSessionSoloAmbient作为我的应用程序的音频会话类别,以便当响铃/静音开关关闭时,我的音频会话将自动静音。

要求2似乎相当困难,因为我需要某种回调,通知或KVO,这将允许我监控交换机的位置,但Apple已经明确表示它不愿意提供正式公开的方式来做到这一点。 也就是说,如果我能找到一种非侵入性的方式来监控交换机的位置,即使是技术上禁止的方式(例如,内部的NSNotification ),我也愿意由Apple运行它。

此外,我宁愿不实施我在别处找到的一些民意调查解决方案。 有关示例,请参阅“相关问题”部分。


我学到了什么(又名什么不行)

  • 至少在iOS版本4和5中,有一个技巧可以通过观察当前音频会话的路由属性来获取交换机的位置。 除了被AVAudioSession类弃用之外,我还可以确认这个技巧不再是一个选项。 当切换振铃/静音开关时,包括已弃用的Audio Session API和当前AVAudioSession类的C函数报告的当前路由不会改变。

  • AVSystemController是一个内部类 ,似乎有很多承诺。 在- (BOOL)toggleActiveCategoryMuted上调用- (BOOL)toggleActiveCategoryMuted确实sharedAVSystemController我的应用程序的音频静音。 此外,当通过音量按钮更改系统音量时,共享单AVSystemController_SystemVolumeDidChangeNotification发布AVSystemController_SystemVolumeDidChangeNotification通知。 不幸的是,这个通知不是为响应环/静音开关的变化而发布的(虽然这个可疑的来源说它应该 )。

  • 据我所知, 任何对象都没有发布NSNotification来响应响铃/静音开关位置的变化。 在将自己添加为默认中心中所有通知的观察者后,我得出了这个结论:

     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNotification:) name:nil object:nil]; 

    然后切换响铃/静音开关。 没有。

  • AVSystemController类有一个很有前途的签名方法:

     - (BOOL)getActiveCategoryMuted:(BOOL*)arg1; 

    但是,这有两个问题:

    1. arg1指向的返回值和BOOL似乎都没有响应切换环/静音开关而改变。
    2. 由于方法签名,这种方法(据我所知)并不是KVO的候选者。

  • 我怀疑当静音开关改变时,某些对象会发送一些其他对象作为GSEventRef ,因为我在事件类型的声明中看到以下内容:

     kGSEventRingerOff = 1012, kGSEventRingerOn = 1013, 

    但是,我很确定我无法拦截这些消息,即使我可以,这也不仅仅是“一点点”的干扰。


为什么我相信这是可能的

简单地说:Instagram应用程序基本上表现出这种行为。 观看video时,它会考虑铃声/静音开关的设置,但在开关关闭时会显示一个图标。 图标消失并在移动开关后立即重新出现,我认为它必须是基于事件的,而不是轮询。


相关问题

  • 这个问题可以追溯到iOS 4,并使用我在上面的第一个项目中提到的方法。

  • 这个问题与上面的问题非常相似。

  • 这个问题(更多)更新,询问iOS 7.但是,因为我愿意接受私有API规则的最小侵入性破坏,我认为这是一个与我自己不同的问题。

  • 这个答案建议使用我非常希望避免的轮询方法。