Как подключить аудио к Bluetooth при воспроизведении с помощью AVPlayer

Я воспроизвожу аудио с URL-адреса с помощью AVPlayer, но когда iPhone подключен к Bluetooth-устройству, он не воспроизводится через Bluetooth, как играть через Bluetooth, если он подключен, я вижу некоторые сообщения в SO, но ни один из них четко объясняются. Ниже мой код.

    -(void)playselectedsong{

    AVPlayer *player = [[AVPlayer alloc]initWithURL:[NSURL URLWithString:urlString]];
    self.songPlayer = player;
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(playerItemDidReachEnd:)
                                                 name:AVPlayerItemDidPlayToEndTimeNotification
                                               object:[songPlayer currentItem]];
    [self.songPlayer addObserver:self forKeyPath:@"status" options:0 context:nil];
    [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(updateProgress:) userInfo:nil repeats:YES];

    [self.songPlayer play];

}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {

    if (object == songPlayer && [keyPath isEqualToString:@"status"]) {
        if (songPlayer.status == AVPlayerStatusFailed) {
            NSLog(@"AVPlayer Failed");

        } else if (songPlayer.status == AVPlayerStatusReadyToPlay) {
            NSLog(@"AVPlayerStatusReadyToPlay");


        } else if (songPlayer.status == AVPlayerItemStatusUnknown) {
            NSLog(@"AVPlayer Unknown");

        }
    }
}

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

 //  code here to play next sound file

}

Ответ 1

Попробуйте это

UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;
AudioSessionSetProperty (kAudioSessionProperty_AudioCategory,
                         sizeof(sessionCategory),&sessionCategory);

// Set AudioSession
NSError *sessionError = nil;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionAllowBluetooth error:&sessionError];

UInt32 doChangeDefaultRoute = 1;
AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryEnableBluetoothInput, sizeof(doChangeDefaultRoute), &doChangeDefaultRoute);

Ответ 2

Вам нужно установить категорию и параметры на AVAudioSession.

Попробуйте это, когда приложение запустится:

//configure audio session
NSError *setCategoryError = nil;
BOOL setCategorySuccess = [[AVAudioSession sharedInstance]
                           setCategory:AVAudioSessionCategoryPlayback
                           withOptions:AVAudioSessionCategoryOptionAllowBluetooth
                           error:&setCategoryError];

if (setCategorySuccess) {
    NSLog(@"Audio Session options set.");
} else {
    NSLog(@"WARNING: Could not set audio session options.");
}

Ответ 3

Для Swift 3.1

Краткая версия:

let audioSession = AVAudioSession.sharedInstance()
do {
    try audioSession.setCategory(AVAudioSessionCategoryRecord, with: [.allowBluetooth])
    try audioSession.setActive(true)
} catch {
    fatalError("Error Setting Up Audio Session")
}

Расширенная версия, чтобы убедиться, что вы используете правильный ввод:

/**
    Check availability of recording and setups audio session
    with prioritized input.
 */
func setupSessionForRecording() {
    let audioSession = AVAudioSession.sharedInstance()
    do {
        try audioSession.setCategory(AVAudioSessionCategoryRecord, with: [.allowBluetooth])
    } catch {
        fatalError("Error Setting Up Audio Session")
    }
    var inputsPriority: [(type: String, input: AVAudioSessionPortDescription?)] = [
        (AVAudioSessionPortLineIn, nil),
        (AVAudioSessionPortHeadsetMic, nil),
        (AVAudioSessionPortBluetoothHFP, nil),
        (AVAudioSessionPortUSBAudio, nil),
        (AVAudioSessionPortCarAudio, nil),
        (AVAudioSessionPortBuiltInMic, nil),
    ]
    for availableInput in audioSession.availableInputs! {
        guard let index = inputsPriority.index(where: { $0.type == availableInput.portType }) else { continue }
        inputsPriority[index].input = availableInput
    }
    guard let input = inputsPriority.filter({ $0.input != nil }).first?.input else {
        fatalError("No Available Ports For Recording")
    }
    do {
        try audioSession.setPreferredInput(input)
        try audioSession.setActive(true)
    } catch {
        fatalError("Error Setting Up Audio Session")
    }
}

/**
    Check availability of playing audio and setups audio session
    with mixing audio.
 */
func setupSessionForPlaying() {
    let audioSession = AVAudioSession.sharedInstance()
    do {
        try audioSession.setCategory(AVAudioSessionCategoryPlayback, with: [.mixWithOthers])
        try audioSession.setActive(true)
    } catch {
        fatalError("Error Setting Up Audio Session")
    }
}

Основная идея, что у вас есть 2 функции для изменения настроек аудио сессии. Используйте setupSessionForRecording перед записью и setupSessionForPlaying перед воспроизведением звука.

Важно использовать AVAudioSessionCategoryRecord и AVAudioSessionCategoryPlayback, но не AVAudioSessionCategoryPlayAndRecord, из-за ошибки. Используйте AVAudioSessionCategoryPlayAndRecord только в том случае, если вам действительно нужно играть и записывать звук одновременно.