iOS 音频播放时听筒及扬声器切换
<pre>
[[UIDevice currentDevice] setProximityMonitoringEnabled:YES];
//建议在播放之前设置yes,播放结束设置NO,这个功能是开启红外感应//添加监听
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sensorStateChange:) name:@"UIDeviceProximityStateDidChangeNotification" object:nil];
//处理监听触发事件
-
(void)sensorStateChange:(NSNotificationCenter *)notification{
//如果此时手机靠近面部放在耳朵旁,那么声音将通过听筒输出,并将屏幕变暗(省电啊)
if ([[UIDevice currentDevice] proximityState] == YES) { NSLog(@"Device is close to user");
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil]; } else {
NSLog(@"Device is not close to user");
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
}
}
//初始化播放器的时候如下设置
UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(sessionCategory), &sessionCategory);
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute, sizeof (audioRouteOverride), &audioRouteOverride);
AVAudioSession *audioSession = [AVAudioSession sharedInstance];//默认情况下扬声器播放[audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];[audioSession setActive:YES error:nil];
</pre>
<p> UIDevice 中有两个近距离传感器的属性:proximityMonitoringEnabled 和 proximityState。这两个属性都是 iOS 3.0 及以上才支持的。
//添加近距离事件监听,添加前先设置为YES,如果设置完后还是NO的读话,说明当前设备没有近距离传感器></p>
<pre>
[[UIDevice currentDevice] setProximityMonitoringEnabled:YES];
if ([UIDevice currentDevice].proximityMonitoringEnabled == YES) { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sensorStateChange:)name:UIDeviceProximityStateDidChangeNotification object:nil];
}
//删除近距离事件监听[[UIDevice currentDevice] setProximityMonitoringEnabled:YES];
if ([UIDevice currentDevice].proximityMonitoringEnabled == YES) {
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceProximityStateDidChangeNotification object:nil];
}
[[UIDevice currentDevice] setProximityMonitoringEnabled:NO];
pragma mark - 处理近距离监听触发事件
-(void)sensorStateChange:(NSNotificationCenter *)notification
{
//如果此时手机靠近面部放在耳朵旁,那么声音将通过听筒输出,并将屏幕变暗(省电啊)
if ([[UIDevice currentDevice] proximityState] == YES)//黑屏
{
NSLog(@"Device is close to user");
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
}else//没黑屏幕
{
NSLog(@"Device is not close to user");
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
if (![MTool isPlayRecodering]) {//没有播放了,也没有在黑屏状态下,就可以把距离传感器关了
[[UIDevice currentDevice] setProximityMonitoringEnabled:NO];
}
}
}
</pre>
<h1> 注意事项(也就是我说的问题)</h1>
<p> 对于不希望启动接近传感器功能的应用,如果需要进行扬声器和听筒进行切换过程中,则必须通过启用接近传感器来进行声音输出模式的切换,在此时,必须要注意, 如果当声音通过听筒进行播放完毕时,在播放完毕时,此时仍在听筒模式输出,如果此时关闭传感器功能,则导致在离开听筒时,由于传感器功能已经关闭,应用无 法再次收到注册的传感器变更通知,而此时如果未能将底层的声音输出模式切换,则导致相关的声音输出仍从听筒中输出,即使引起传感器反映的障碍已经离开传感 器作用范围,但应用中获取的传感器状态仍未接近状态,使根据传感器状态进行切换声音输出模式操作失效。
特殊情况:
在iPhone 4s及iPhone5中,在接近传感器功能关闭后,如果此时传感器状态为YES,则在再次启动声音传感器时,不会收到传感器的变更通知;
在iPhone 4中,在接近传感器功能关闭后,如果此时传感器状态为YES,则在再次启动声音传感器时,会先收到一次传感器的变更通知;
此 问题的解决方案:当在传感器功能开始时,如果此时传感器传感状态为YES时,此时声音播放结束,仍未出发传感器状态变更时,此时不关闭传感器功能。当引起 传感器反映的障碍已经离开传感器作用范围,此时会收到传感器变更通知,在变更通知中检测当前传感器状态是否为开启状态及声音播放状态,如果在传感器状态为 YES时,而此时需要开启传感器功能的操作(如声音播放功能)已经结束时,则将传感器功能关闭即可;-------也就是说,在不是黑屏的状态下,关闭近传感器功能。就没什么问题了</p>
<h1> 手动切换两种模式</h1>
解决方案:添加长按手势,切换为另一种模式。
代码片段:
<pre>
UILongPressGestureRecognizer *longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self
action:@selector(longPressed:)];
[longPressGestureRecognizer setMinimumPressDuration:1.0f];
[longPressGestureRecognizer setAllowableMovement:50.0];
[self.bubbleBgImageView addGestureRecognizer:longPressGestureRecognizer];
[longPressGestureRecognizer release];
---------
- (void)longPressed:(UILongPressGestureRecognizer *) gestureRecognizer
{
switch (gestureRecognizer.state)
{
case UIGestureRecognizerStateEnded:
break;
case UIGestureRecognizerStateCancelled:
break;
case UIGestureRecognizerStateFailed:
break;
case UIGestureRecognizerStateBegan:
if ([self.voiceDelegate respondsToSelector:@selector(BaseChartVoiceLongPressed)])
{
[self.voiceDelegate BaseChartVoiceLongPressed];
}
break;
case UIGestureRecognizerStateChanged:
break;
default:
break;
}
}
-------------
pragma mark BaseChartCellDelegate
- (void)BaseChartVoiceLongPressed {
NSLog(@"voice long Pressed");
if ([[[AVAudioSession sharedInstance] category] isEqualToString:AVAudioSessionCategoryPlayback]){
//切换为听筒播放
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
[self showTipInfo:@"切换为听筒模式"];
}
else{
//切换为扬声器播放
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[self showTipInfo:@"切换为扬声器模式"];
}
}
</pre>