How can I detect whether an HFP or A2DP is connected in iOS?

ぐ巨炮叔叔 提交于 2020-08-07 08:03:51

问题


I am working on a project which can play music via HFP device. But here's a problem that I want to detect whether an HFP or A2DP is connected when music is playing.

Now I am using the AVFoundation framework to do this. Here's the code:

- (BOOL)isConnectedToBluetoothPeripheral
{
    BOOL isMatch = NO;
    NSString* categoryString = [AVAudioSession sharedInstance].category;
    AVAudioSessionCategoryOptions categoryOptions = [AVAudioSession sharedInstance].categoryOptions;
    if ((![categoryString isEqualToString:AVAudioSessionCategoryPlayAndRecord] &&
         ![categoryString isEqualToString:AVAudioSessionCategoryRecord]) ||
        categoryOptions != AVAudioSessionCategoryOptionAllowBluetooth)
    {
        NSError * error = nil;
        [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord
                                         withOptions:AVAudioSessionCategoryOptionAllowBluetooth
                                               error:&error];
        if (error) {
            [[AVAudioSession sharedInstance] setCategory:categoryString
                                             withOptions:categoryOptions
                                                   error:&error];
            return isMatch;
        }
    }
    
        NSArray * availableInputs = [AVAudioSession sharedInstance].availableInputs;
        for (AVAudioSessionPortDescription *desc in availableInputs)
        {
            if ([[desc portType] isEqualToString:AVAudioSessionPortBluetoothA2DP] || [[desc portType] isEqualToString:AVAudioSessionPortBluetoothHFP])
            {
                    isMatch = YES;
                    break;
            }
        }
        if (!isMatch)
        {
            NSArray * outputs = [[[AVAudioSession sharedInstance] currentRoute] outputs];
            
            for (AVAudioSessionPortDescription * desc in outputs)
            {
                if ([[desc portType] isEqualToString:AVAudioSessionPortBluetoothA2DP] || [[desc portType] isEqualToString:AVAudioSessionPortBluetoothHFP])
                {
                        isMatch = YES;
                        break;
                }
            }
        }
        
        NSError * error = nil;
        [[AVAudioSession sharedInstance] setCategory:categoryString
                                         withOptions:categoryOptions
                                               error:&error];
    
        return isMatch;
}

It works well but cause another problem: when music is playing, using this method to detect HFP connection will make music playing interrupt for about two seconds.

So I tried another way which can reduce the effect of detecting HFP connecting. I am using a flag

static BOOL isHFPConnectedFlag

To indicate whether HFP or A2DP is connected. I use previous method to detect the connection only once (when the app is launching) and save the result into isHFPConnectedFlag. What's more, I observe the AudioSessionRouteChange to sync the connection status:

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

When the route change reason is AVAudioSessionRouteChangeReasonNewDeviceAvailable or AVAudioSessionRouteChangeReasonOldDeviceUnavailable I can know HFP is connected or disconnected. Unfortunately, when I connect some HFP in my iPhone, the system will not post this notification, so I cannot detect the connection in this situation.

Does anyone know the reason or a better way to implements this (Detecting HFP connection without music playing interrupting)?


回答1:


you can use like this!

    -(BOOL) bluetoothDeviceA2DPAvailable {

    BOOL available = NO;
    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    AVAudioSessionRouteDescription *currentRoute = [audioSession currentRoute];

    for (AVAudioSessionPortDescription *output in currentRoute.outputs) {
        if (([[output portType] isEqualToString:AVAudioSessionPortBluetoothA2DP] ||
             [[output portType] isEqualToString:AVAudioSessionPortBluetoothHFP])) {
            available = YES;
            break;
        }
    }
    return available;
}



回答2:


Swift 5 version:

func bluetoothDeviceHFPAvailable() -> Bool {
    let audioSession = AVAudioSession.sharedInstance()
    let currentRoute = audioSession.currentRoute

    for output in currentRoute.outputs {
        if output.portType == .bluetoothHFP || output.portType == .bluetoothA2DP {
            return true
        }
    }

    return false
}


来源:https://stackoverflow.com/questions/37157252/how-can-i-detect-whether-an-hfp-or-a2dp-is-connected-in-ios

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!