关于iOS蓝牙音频断开机制
蓝牙连接,CoreBluetooth通过代码控制的仅仅是对于数据的传递,但是并不能处理对于蓝牙音频的判断。
相对的在对于音频播报软件来说,当与蓝牙配对之后,尤其是导航类软件类似高德导航,在长时间的连接与息屏的情况下,会出现蓝牙音频切换到手机音频播报,但是蓝牙音频却又未断开,导致声音很小,这种状态下体验会很差。
AVAudioSessionRouteChangeReason changeReason = [dict[AVAudioSessionRouteChangeReasonKey] intValue];
switch (changeReason) {
case AVAudioSessionRouteChangeReasonUnknown:
break;
case AVAudioSessionRouteChangeReasonNewDeviceAvailable:
break;
case AVAudioSessionRouteChangeReasonOldDeviceUnavailable:
break;
case AVAudioSessionRouteChangeReasonCategoryChange:
break;
case AVAudioSessionRouteChangeReasonOverride:
break;
case AVAudioSessionRouteChangeReasonWakeFromSleep:
break;
case AVAudioSessionRouteChangeReasonNoSuitableRouteForCategory:
break;
case AVAudioSessionRouteChangeReasonRouteConfigurationChange:
break;
}
通过上面的AVFoundation 监听机制,可以判断:手机音频的切换原因
AVAudioSessionRouteDescription *routeDescription = dict[AVAudioSessionRouteChangePreviousRouteKey];
AVAudioSessionPortDescription *portDescription = [routeDescription.outputs firstObject];
NSString *portType = portDescription.portType;
再次判断类型:得出手机音频切换之前的音频类型:BluetoothA2DPOutput、BluetoothHFP、Speaker、Receiver...
而我所需要的 仅仅是 蓝牙音频的机制: 因此可以进行判断:
BOOL flag1 = [portType isEqualToString:@"BluetoothA2DPOutput"];
BOOL flag2 = [portType isEqualToString:@"BluetoothHFP"];
BOOL flag3 = changeReason == AVAudioSessionRouteChangeReasonOldDeviceUnavailable;
if ((flag1 ||flag2) && flag3){
/*之前的设备是蓝牙 在这里面进行音频播报的通道设置, 重新切换音频通道到蓝牙
设定bool值 ,在音频播报的情况下 ,修改音频category*/
}
下面 我需要切换播报的category:
typedef NS_OPTIONS(NSUInteger, AVAudioSessionCategoryOptions){
/* MixWithOthers is only valid with AVAudioSessionCategoryPlayAndRecord, AVAudioSessionCategoryPlayback, and AVAudioSessionCategoryMultiRoute */
AVAudioSessionCategoryOptionMixWithOthers = 0x1,
/* DuckOthers is only valid with AVAudioSessionCategoryAmbient, AVAudioSessionCategoryPlayAndRecord, AVAudioSessionCategoryPlayback, and AVAudioSessionCategoryMultiRoute */
AVAudioSessionCategoryOptionDuckOthers = 0x2,
/* AllowBluetooth is only valid with AVAudioSessionCategoryRecord and AVAudioSessionCategoryPlayAndRecord */
AVAudioSessionCategoryOptionAllowBluetooth __TVOS_PROHIBITED __WATCHOS_PROHIBITED = 0x4,
/* DefaultToSpeaker is only valid with AVAudioSessionCategoryPlayAndRecord */
AVAudioSessionCategoryOptionDefaultToSpeaker __TVOS_PROHIBITED __WATCHOS_PROHIBITED = 0x8,
/* InterruptSpokenAudioAndMixWithOthers is only valid with AVAudioSessionCategoryPlayAndRecord, AVAudioSessionCategoryPlayback, and AVAudioSessionCategoryMultiRoute */
AVAudioSessionCategoryOptionInterruptSpokenAudioAndMixWithOthers NS_AVAILABLE_IOS(9_0) = 0x11,
/* AllowBluetoothA2DP is only valid with AVAudioSessionCategoryPlayAndRecord */
AVAudioSessionCategoryOptionAllowBluetoothA2DP API_AVAILABLE(ios(10.0), watchos(3.0), tvos(10.0)) = 0x20,
/* AllowAirPlay is only valid with AVAudioSessionCategoryPlayAndRecord */
AVAudioSessionCategoryOptionAllowAirPlay API_AVAILABLE(ios(10.0), tvos(10.0)) __WATCHOS_PROHIBITED = 0x40,
} NS_AVAILABLE_IOS(6_0);
上面代码中,苹果api设定:AVAudioSessionCategoryOptionAllowBluetooth 需AVAudioSessionCategoryPlayAndRecord模式才可以起作用,因此 我们需要重新设定option:
AVAudioSession *session = [AVAudioSession sharedInstance] ;
[session setCategory:AVAudioSessionCategoryPlayAndRecord
withOptions:AVAudioSessionCategoryOptionAllowBluetooth|
AVAudioSessionCategoryOptionAllowBluetoothA2DP|AVAudioSessionCategoryOptionInterruptSpokenAudioAndMixWithOthers
error:nil];
这样就可以在每次播报的时候强制扭转音频到蓝牙,但我感觉这并不是最友好的方式,希望有人提出更加优化的方式。