使用AVAudioPlayer不工作检测iPhone的环/静音/静音开关?

我尝试过使用这些方法来试图检测Ring / Silent开关是否激活:

如何以编程方式感应iPhone静音开关?

AVAudioSession类别不起作用文档指示

但在我的iPhone 4上,“状态”值始终是“扬声器”(并且由CFStringGetLength(状态)返回的长度值始终为7)。 有没有人使用这种方法成功? 如果是这样,在什么样的设备和SDK版本?

我这样称呼它:

- (BOOL)deviceIsSilenced { CFStringRef state; UInt32 propertySize = sizeof(CFStringRef); OSStatus audioStatus = AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state); if (audioStatus == kAudioSessionNoError) { NSLog(@"audio route: %@", state) // "Speaker" regardless of silent switch setting, but "Headphone" when my headphones are plugged in return (CFStringGetLength(state) <= 0); } return NO; } -(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { AVAudioSession *audioSession = [AVAudioSession sharedInstance]; audioSession.delegate = self; [audioSession setCategory:AVAudioSessionCategoryAmbient error:nil]; [audioSession setActive:YES error:nil]; NSLog(@"muted? %i", [self deviceIsSilenced]); ... } 

我想也许一些其他的(更准确的)kAudioSessionProperty事件触发时,手机上的物理交换机…切换。 任何人有任何想法?

顺便说一句,我使用AVAudioSessionCategoryAmbient类别与我的[AVAudioSession sharedInstance]。

更新:我也尝试过使用不同的audio类别,以及其他一些audio会话属性,在屏蔽/取消静音交换机时似乎没有启动。 🙁

2014年1月1日更新:这是一个黑客,我遇到了一个崩溃,同时在我的iPhone 5S多任务处理,但SoundSwitch库链接在新的接受的答案是要走的路,如果你想检测无声开关。 它甚至可以在iOS 7中运行。

我经历了这个VSSilentSwitch库。
没有为我工作(实际上开始使用audio时不起作用)。
我正在考虑他是怎么做到的,然后意识到,当我们沉默的时候,一旦声音开始播放,audio完成呼叫就被调用。
要更具体些:
使用AudioServicesPlaySystemSound播放的系统声音将在其开始后立即完成播放。
当然,这只适用于尊重无声开关的audio类别(默认AVAudioSessionCategoryAmbient尊重它)。
所以诀窍是创build一个系统声音,最好是一个沉默的声音,并不断播放它,同时检查从播放到完成所花的时间(使用AudioServicesAddSystemSoundCompletion安装完成过程)。
如果完成过程很快被调用(允许一些阈值) – 这意味着无声开关打开。
这个诀窍有许多警告,其中最大的一个就是它不适用于所有audio类别。
如果您的应用程序在后台播放audio,请确保您在后台停止此testing,否则您的应用将永远在后台运行(并且也会被苹果拒绝)。

好吧,我发现答案感谢开发者论坛的人,你们不会喜欢它!

我已经收到了苹果的回应。

他们说他们没有,也没有提供检测硬件静音开关的方法,也不打算这样做。

🙁

国际海事组织检测无声开关,并通知用户,如果他们已经忘记它是肯定有价值…我有人抱怨说,他们没有任何声音,无声的开关是原因! 好吧。

PS:如果您希望Apple添加此function(当然您也可以!),请在http://bugreport.apple.com/上提供“iPhone SDK”的新“增强”错误报告。

更新:虽然仍然没有官方的方法来检查静音开关的状态,但是有一个名为“SoundSwitch”的解决方法/库,似乎可以做到这一点。 查看链接的新接受的答案。

“但是,如果有人可以告诉我们如何使用这个AudioSessionProperty_AudioRouteDescription,赏金是他的权利。

那么,只是NSLog()的结果,你会得到

 routes: { "RouteDetailedDescription_Inputs" = ( ); "RouteDetailedDescription_Outputs" = ( { "RouteDetailedDescription_PortType" = Speaker; } ); } 

不幸的是,我在iPad2 / OS 5.0上获得了相同的结果,既静音又不静音。 所以它似乎在function上等同于kAudioSessionProperty_AudioRoute,那里没有喜悦。

在开发板上看,发现这是一个经常遇到的问题,总结得最好

“我在七月份把这个问题报告了rdar:// 9781189,这个问题现在仍然存在于通用汽车公司。”

所以是的…确定看起来像你在5.0的SOL。

附录:

“但是,如果你正在login的CFDictionary如何访问”RouteDetailedDescription_PortType“键?

免费桥接是你的朋友。

  CFDictionaryRef asCFType = nil; UInt32 dataSize = sizeof(asCFType); AudioSessionGetProperty(kAudioSessionProperty_AudioRouteDescription, &dataSize, &asCFType); NSDictionary *easyPeasy = (NSDictionary *)asCFType; NSDictionary *firstOutput = (NSDictionary *)[[easyPeasy valueForKey:@"RouteDetailedDescription_Outputs"] objectAtIndex:0]; NSString *portType = (NSString *)[firstOutput valueForKey:@"RouteDetailedDescription_PortType"]; NSLog(@"first output port type is: %@!", portType); 

产生

第一个输出端口types是:扬声器!

许多常见的CFType被桥接到更方便的types。

http://developer.apple.com/library/ios/#documentation/CoreFoundation/Conceptual/CFDesignConcepts/Articles/tollFreeBridgedTypes.html

现在,需要一点练习来正确地猜测,如上所述,魔法咒语会从字典中获得有用的东西。 沿着这些线路的class级助手将帮助你加快速度:

  - (void)whatsInThis:(CFDictionaryRef)thingy { NSDictionary *dict = (NSDictionary *)thingy; for (NSString *key in dict.allKeys) { id value = [dict valueForKey:key]; NSLog(@"key: %@ value type %@", key, [value class]); if ([value isKindOfClass:[NSArray class]]) { NSArray *array = (NSArray *)value; for (id item in array) { NSLog(@" -- object type %@", [item class]); if ([item isKindOfClass:[NSDictionary class]]) [self whatsInThis:item]; } } } } 

这对于我们手头的字典来说产生了(为了清楚起见,添加了缩进)

 key: RouteDetailedDescription_Inputs value type __NSCFArray key: RouteDetailedDescription_Outputs value type __NSCFArray -- object type __NSCFDictionary key: RouteDetailedDescription_PortType value type __NSCFString 

它可以让你确切地知道你可以从原始日志中推导出什么,知道NSLog显示()内的数组和{}内的字典,所以正确的演员是非常可猜的。 但是一些CFType结构比这更难parsing。

尝试在您的调用上方插入此行以在deviceIsSilenced内的AudioSessionGetProperty

AudioSessionInitialize(NULL,NULL,NULL,NULL);

当开关closures时,应该开始返回空string(例如,如果BT耳机或附件连接,将显示耳机和其他一些状态)。

FWIW我不相信公共API中有什么东西会在实际的开关移动时触发。

我认为你有错误的印象。 路线就是它要去的地方。 你想知道音量水平。 使用kAudioSessionProperty_CurrentHardwareOutputVolume

好吧,使用CMD +单击后跟随kAudioSessionProperty_AudioRoute ,我发现这:(

 /*! @enum AudioSession audio categories states @abstract Deprecated AudioSession properties @constant kAudioSessionProperty_AudioRoute Deprecated in iOS 5.0; Use kAudioSessionProperty_AudioRouteDescription */ enum { kAudioSessionProperty_AudioRoute = 'rout', // CFStringRef (get only) }; 

事实certificate,我们必须使用kAudioSessionProperty_AudioRouteDescription ,但这个家伙返回一个CFDictionaryRef什么的,我绝对不知道如何处理它….

我做了这个答案,如果没有人告诉我们如何使用kAudioSessionProperty_AudioRouteDescription ,我会尝试接受我的答案…

但是,如果有人可以告诉我们如何使用这个kAudioSessionProperty_AudioRouteDescription ,赏金是他的。

编辑:

显然,这是一个iOS 5的问题。 我之前没有说过,因为它看起来太明显了,但后来我觉得它可能不像search引擎那么明显。如果你明白我的意思。

所以,iOS 5不能使用iPhone上的静音/静音开关,因为这个被推荐使用的值。

find这个图书馆http://www.verietassoftware.com/index.php?option=com_content&view=article&id=27&Itemid=115

苹果会允许这些东西吗? 这是一个500Kb库,在audio和手机设置上做了一些黑魔法