简体   繁体   English

如何检测蓝牙耳机是否已插入 IOS 8?

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

In my project, I use AVAudioSession to detect any headphone is plugged or unplugged.在我的项目中,我使用AVAudioSession来检测任何耳机的插入或拔出。 But in this case, I can't detect when bluetooth device is plugged.但在这种情况下,我无法检测到蓝牙设备何时插入。 Here is my code for headphone state.这是我的耳机状态代码。

 - (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];

}

So how can I detect if a bluetooth headset plugged or not iOS 8?那么如何检测蓝牙耳机是否已插入 iOS 8?

You can detect currently active bluetooth output devices (instead of input devices)您可以检测当前活动的蓝牙输出设备(而不是输入设备)

Swift Code: 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
}

Bluetooth devices are based on the following question: What's the difference among AVAudioSessionPortBluetoothHFP, A2DP and LE?蓝牙设备基于以下问题: AVAudioSessionPortBluetoothHFP、A2DP和LE之间有什么区别?

I hope it helps someone我希望它可以帮助某人


Edit for Swift 5.1 (Thanks iago849 for the fix)为 Swift 5.1 编辑(感谢iago849的修复)

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

I was able to detect whether a bluetooth headset (HFP) device was currently connected using the following:我能够使用以下方法检测当前是否连接了蓝牙耳机 (HFP) 设备:

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

However, your AVAudioSession category must be set as AVAudioSessionCategoryPlayAndRecord in order for this to work.但是,您的 AVAudioSession 类别必须设置为 AVAudioSessionCategoryPlayAndRecord 才能使其工作。 If it isn't, the port will not show up in the list even if the HFP device is connected.如果不是,即使 HFP 设备已连接,该端口也不会显示在列表中。

You can detect it with routeChangeNotification :您可以使用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
            }
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM