如何检测蓝牙耳机是否插入IOS8?

How to detect if a bluetooth headset plugged or not IOS 8?

在我的项目中,我使用 AVAudioSession 来检测任何耳机是否插入或拔出。但在这种情况下,我无法检测到蓝牙设备何时插入。这是我的耳机状态代码。

 - (void)audioRouteChangeListenerCallback:(NSNotification*)notification
    {

    NSDictionary *interuptionDict = notification.userInfo;

    NSInteger routeChangeReason = [[interuptionDict valueForKey:AVAudioSessionRouteChangeReasonKey] integerValue];

    switch (routeChangeReason) {

        case AVAudioSessionRouteChangeReasonNewDeviceAvailable:
            //NSLog(@"AVAudioSessionRouteChangeReasonNewDeviceAvailable");

            NSLog(@"Headphone/Line plugged in");

            [_soundButtonOutlet setImage:[UIImage imageNamed:@"sound-on.png"] forState:UIControlStateNormal];

            _headSetState=YES;

            break;

        case AVAudioSessionRouteChangeReasonOldDeviceUnavailable:
            NSLog(@"AVAudioSessionRouteChangeReasonOldDeviceUnavailable");

            NSLog(@"Headphone/Line was pulled. Stopping player....");

             [_soundButtonOutlet setImage:[UIImage imageNamed:@"sound-off.png"] forState:UIControlStateNormal];
            if(_isPlaying==YES)
            {


            [self.player pause];

            [_audioButtonOutlet setImage:[UIImage imageNamed:@"play.png"] forState:UIControlStateNormal];

            _isPlaying=NO;

            }
            _headSetState=NO;

            break;

        case AVAudioSessionRouteChangeReasonCategoryChange:
            // called at start - also when other audio wants to play
            NSLog(@"AVAudioSessionRouteChangeReasonCategoryChange");


            break;
    }



- (BOOL)isHeadsetPluggedIn

{

    AVAudioSessionRouteDescription* route = [[AVAudioSession sharedInstance] currentRoute];
    for (AVAudioSessionPortDescription* desc in [route outputs]) {

        if ([[desc portType] isEqualToString:AVAudioSessionPortHeadphones])
        {
        [_soundButtonOutlet setImage:[UIImage imageNamed:@"sound-on.png"] forState:UIControlStateNormal];
            _headSetState=YES;
            return YES;
        }
        else
        {
    [_soundButtonOutlet setImage:[UIImage imageNamed:@"sound-off.png"] forState:UIControlStateNormal];
            _headSetState=NO;
            return NO;

        }
    }


    return NO;
}

}


- viewWillAppear  {

 [AVAudioSession sharedInstance];

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

[self isHeadsetPluggedIn];

}

那么如何检测蓝牙耳机是否插入iOS8?

我能够使用以下方法检测当前是否连接了蓝牙耳机 (HFP) 设备:

NSArray *arrayInputs = [[AVAudioSession sharedInstance] availableInputs];
for (AVAudioSessionPortDescription *port in arrayInputs)
{
    if ([port.portType isEqualToString:AVAudioSessionPortBluetoothHFP])
    {
        bHas = YES;
        break;
    }
}

但是,您的 AVAudioSession 类别必须设置为 AVAudioSessionCategoryPlayAndRecord 才能使其正常工作。否则,即使连接了 HFP 设备,该端口也不会显示在列表中。

您可以检测当前活动的蓝牙输出设备(而不是输入设备)

Swift代码:

import AVFoundation
func bluetoothAudioConnected() -> Bool{
  let outputs = AVAudioSession.sharedInstance().currentRoute.outputs
  for output in outputs{
    if output.portType == AVAudioSessionPortBluetoothA2DP || output.portType == AVAudioSessionPortBluetoothHFP || output.portType == AVAudioSessionPortBluetoothLE{
      return true
    }
  }
  return false
}

蓝牙设备基于以下问题:What's the difference among AVAudioSessionPortBluetoothHFP, A2DP and LE?

希望对大家有所帮助


编辑 Swift 5.1(感谢 iago849 的修复)

var bluetoothDeviceConnected: Bool {
    !AVAudioSession.sharedInstance().currentRoute.outputs.compactMap {
        ([=11=].portType == .bluetoothA2DP ||
        [=11=].portType == .bluetoothHFP ||
        [=11=].portType == .bluetoothLE) ? true : nil
    }.isEmpty
}

您可以使用 routeChangeNotification 检测到它:

    func activateHeadPhonesStatus(){
        NotificationCenter.default.addObserver(self, selector: #selector(audioRouteChangeListener(_:)), name: AVAudioSession.routeChangeNotification, object: nil)
    }
    
    @objc func audioRouteChangeListener(_ notification:Notification) {
        guard let userInfo = notification.userInfo,
              let reasonValue = userInfo[AVAudioSessionRouteChangeReasonKey] as? UInt,
              let reason = AVAudioSession.RouteChangeReason(rawValue:reasonValue) else {
            return
        }
        if reason == .newDeviceAvailable {
            let session = AVAudioSession.sharedInstance()
            for output in session.currentRoute.outputs where output.portType == AVAudioSession.Port.bluetoothA2DP {
                print("Bluetooth Headphone Connected")
                break
            }
        }
    }