初始化音频会话
在播放器初始化时,需要正确配置音频会话类别。默认情况下使用扬声器播放。
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
audioSession.active = YES;
自动切换逻辑(接近传感器)
利用 UIDevice 的接近传感器功能,当手机靠近耳朵时自动切到听筒,远离时切回扬声器。这能提升通话或语音播放时的体验。
开启监听
建议在播放前开启,播放结束后关闭。注意检查设备是否支持该传感器,并非所有 iOS 设备都配备近距离传感器。
[[UIDevice currentDevice] setProximityMonitoringEnabled:YES];
if ([UIDevice currentDevice].proximityMonitoringEnabled == YES) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sensorStateChange:) name:UIDeviceProximityStateDidChangeNotification object:nil];
}
处理状态变化
当传感器触发时,根据状态调整音频会话类别。如果此时手机靠近面部放在耳朵旁,声音将通过听筒输出,并将屏幕变暗。
- (void)sensorStateChange:(NSNotification *)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];
// 关键点:非黑屏状态下且无录音需求时,可关闭传感器以省电并避免状态锁死
// 实际项目中需结合业务判断,例如是否有后台录音等
}
}
注意事项与坑点
在实际应用中,传感器的生命周期管理至关重要。如果当声音通过听筒进行播放完毕时,仍在听筒模式输出,此时若直接关闭传感器功能,可能导致应用无法再次收到注册的传感器变更通知。
特别是在 iPhone 4s 及 iPhone 5 中,在接近传感器功能关闭后,如果此时传感器状态为 YES,则在再次启动声音传感器时,不会收到传感器的变更通知;而在 iPhone 4 中则会先收到一次通知。
解决方案: 当在传感器功能开始时,如果当前传感状态为 YES 且声音播放结束仍未触发传感器状态变更时,不要立即关闭传感器功能。等待收到传感器变更通知(变为 NO),确认障碍已离开传感器作用范围后,再将传感器功能关闭。简单来说,不要在黑屏状态下关闭近传感器功能。
手动切换模式
除了自动检测,也可以添加长按手势允许用户手动切换,增加交互灵活性。
UILongPressGestureRecognizer *longPressRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressed:)];
longPressRecognizer.minimumPressDuration = 1.0;
[self.view addGestureRecognizer:longPressRecognizer];
- (void)longPressed:(UILongPressGestureRecognizer *)gestureRecognizer {
if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
AVAudioSession *session = [AVAudioSession sharedInstance];
if ([session.category isEqualToString:AVAudioSessionCategoryPlayback]) {
[session setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
// 提示用户切换为听筒
} else {
[session setCategory:AVAudioSessionCategoryPlayback error:nil];
// 提示用户切换为扬声器
}
}
}

