избежать остановки подключения гарнитуры AVAudioPlayer в iOS

В своем приложении для iPhone я использую AVAudioPlayer для воспроизведения песен ... Но когда я подключаю или подключаю гарнитуру во время воспроизведения песни, она автоматически останавливает AVAudioPlayer ... Мне нужно запустить аудиоплеер, даже если эти изменения происходят ... любые идеи будут оценены. Спасибо заранее.

 mtg16902 авг. 2013 г., 18:40
Вы нашли решение для этого? Я'Я сталкиваюсь с той же проблемой. Я'используя audioRouteChangeListenerCallback, нет специально остановить / приостановить аудио, и неНапомним, что эта проблема возникла в старых версиях iOS. Я использую AVAudioPlayer и AVAudioRecorder для воспроизведения и записи одновременно. Ранее я портировал только воспроизведение потоков в класс стримеров, который использует AudioQueue, и звук прекрасно воспроизводится при повторном подключении и отключении наушников.

Ответы на вопрос(6)

Решение Вопроса

Я нашел ответ.

Просто мы должны импортировать следующие

#import 
#import 

и напиши этот код

//Play the Event in Background
NSError *setCategoryErr = nil;
NSError *activationErr  = nil;
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: &setCategoryErr];
[[AVAudioSession sharedInstance] setActive: YES error: &activationErr];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
UIBackgroundTaskIdentifier newTaskId = UIBackgroundTaskInvalid;
newTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL];

Теперь его постоянно играть, даже я подключен &на ухо телефона.

 bk13824 июн. 2015 г., 18:45
Не могли бы вы также объяснить, что этот код делает или изменяет? Это'не очень очевидно ...
 Martin03 мая 2016 г., 10:37
Не очень хорошая помощь. Ваш код, похоже, не связан с вашей проблемой. Могли бы вы объяснить?
 user299342227 июн. 2015 г., 16:02
А не было»не решить проблему для меня. какие-либо другие предложения?

Свифт 3

Настройте плеер - воспроизводите аудио (даже в беззвучном режиме) и отключайте музыку / подкасты:

let audioSession = AVAudioSession.sharedInstance()
_ = try? audioSession.setCategory(AVAudioSessionCategoryPlayback, with: .duckOthers)
_ = try? audioSession.setActive(true)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(audioRouteChanged), name: .AVAudioSessionRouteChange, object: nil)

Наблюдатель за изменением маршрута (исправление для отключения наушников во время воспроизведения):

func audioRouteChanged(note: Notification) {
  if let userInfo = note.userInfo {
    if let reason = userInfo[AVAudioSessionRouteChangeReasonKey] as? Int {
      if reason == AVAudioSessionRouteChangeReason.oldDeviceUnavailable.hashValue {
        // headphones plugged out
        player.play()
      }
    }
  }
}

Swift 2

let audioSession = AVAudioSession.sharedInstance()
_ = try? audioSession.setCategory(AVAudioSessionCategoryPlayback, withOptions: .DuckOthers)
_ = try? audioSession.setActive(true)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(audioRouteChanged), name: AVAudioSessionRouteChangeNotification, object: nil)

Наблюдатель за изменением маршрута:

func audioRouteChanged(note: NSNotification) {
  if let userInfo = note.userInfo {
    if let reason = userInfo[AVAudioSessionRouteChangeReasonKey] as? Int {
      if reason == AVAudioSessionRouteChangeReason.OldDeviceUnavailable.hashValue {
        // headphones plugged out -> continue playback
        player.play()
      }
    }
  }
}

Я знаю, что это старый пост, но я провел некоторое исследование по этому поводу. Ответ @Martin был верным, и я использую NSNotificationCenter, но я использую Swift3, так что это то, что вы можете получить с уведомлением.userInfo

case AVAudioSessionInterruptionNotificationKey
/* value is an NSNumber representing an AVAudioSessionInterruptionType */

case AVAudioSessionInterruptionOptionsKey */
/* Only present for end interruption events.  Value is of type AVAudioSessionInterruptionOptions.*/

case AVAudioSessionRouteChangeReasonKey */
/* value is an NSNumber representing an AVAudioSessionRouteChangeReason */
    case unknown
    case newDeviceAvailable
    case oldDeviceUnavailable
    case categoryChange
    case override 
    case wakeFromSleep
    case noSuitableRouteForCategory
    case routeConfigurationChange

case AVAudioSessionRouteChangePreviousRouteKey * */
/* value is AVAudioSessionRouteDescription * */
    case input
    case output

case AVAudioSessionSilenceSecondaryAudioHintTypeKey */
/* value is an NSNumber representing an AVAudioSessionSilenceSecondaryAudioHintType */

Вот метод в swift3

func audioSessionRouteChange(notification: NSNotification) {

    if let userInfo = notification.userInfo {

        print("Notification: AVAudioSessionInterruptionTypeKey = \(userInfo[AVAudioSessionInterruptionTypeKey])")
        print("Notification: AVAudioSessionInterruptionOptionKey = \(userInfo[AVAudioSessionInterruptionOptionKey])")
        print("Notification: AVAudioSessionSilenceSecondaryAudioHintTypeKey = \(userInfo[AVAudioSessionSilenceSecondaryAudioHintTypeKey])")

        if let reason = userInfo[AVAudioSessionRouteChangeReasonKey] as? Int {

            print("Notification: AVAudioSessionRouteChangeReasonOldDeviceUnavailable")

            if reason == AVAudioSessionRouteChangeReason.oldDeviceUnavailable.hashValue {

                print("Notification: Headphones out")
            }

            if reason == AVAudioSessionRouteChangeReason.newDeviceAvailable.hashValue {

                print("Notification: Headphones in")
            }
        }

        if let description = userInfo[AVAudioSessionRouteChangePreviousRouteKey] as? AVAudioSessionRouteDescription {

            // here you can check previous input and output 
            // po description.outputs[0].portType == AVAudioSessionPortBuiltInSpeaker

            print("Notification: AVAudioSessionRouteChangePreviousRouteKey Inputs: \(description.inputs)")
            print("Notification: AVAudioSessionRouteChangePreviousRouteKey Outputs: \(description.outputs)")
        }
    }
}

@ Мартин почти прав, кроме случаев, когда мы получаемAVAudioSessionRouteChangeNotification уведомление, звук может все еще играть, вы должны проверить игрокаrate имущество. Если он равен нулю, играйте, иначе вы должны соблюдатьrate, когда он изменится на ноль, играть в нее. Проверитьссылка на сайт

Другое примечаниеAVAudioSessionRouteChangeNotification публикуется во вторичном потоке (не в главном), вы должны отправить его в основной поток, если это необходимо.

вы должны сказатьAVAudioSession аудио поведение вашего приложения. Apple, это названиекатегория аудио сеанса, может быть установлен

[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error:&setCategoryErr];

Например, :AVAudioSessionCategoryPlayback

При использовании этой категории звук вашего приложения продолжается с переключателем «Без звука», установленным в бесшумный режим или при блокировке экрана. (Переключатель называется iPhone / Ring / Silent).

Эта категория обычно не позволяет микшировать звук из других приложений с вашим приложением. 'с аудио. Чтобы разрешить смешивание для этой категории, используйте свойство kAudioSessionProperty_OverrideCategoryMixWithOthers.

Затем, как только аудио сессия установлена, приложение ответит на некоторые звуковые уведомления, такие какAVAudioSessionInterruptionNotification или жеAVAudioSessionRouteChangeNotification

Чтобы ответить на оригинальный вопрос,AVAudioSessionRouteChangeNotification вызывается, когда аудио-маршрут был изменен (например: плагин / плагин для гарнитуры, но также отключение устройства Bluetooth, ...). С помощью небольшого кода мы можем найти причину изменения маршрута. И, в нашем случае, запустите плеер снова, или гарнитура была отключена.

- (void)viewDidLoad {
    [super viewDidLoad];

    NSError *setCategoryErr;
    [[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error:&setCategoryErr];

    // Detects when the audio route changes (ex: jack unplugged)
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioHardwareRouteChanged:) name:AVAudioSessionRouteChangeNotification object:nil];
    // Don't forget to remove notification in dealloc method!!
}

- (void)audioHardwareRouteChanged:(NSNotification *)notification {
    NSInteger routeChangeReason = [notification.userInfo[AVAudioSessionRouteChangeReasonKey] integerValue];
    if (routeChangeReason == AVAudioSessionRouteChangeReasonOldDeviceUnavailable) {
        // if we're here, the player has been stopped, so play again!
        [self.player play];
    }
}

В заключение также подумайте о пользователе, который на скучной встрече случайно отключил свою гарнитуру. У него не было бы такого поведения, которое заставляло бы устройство внезапно кричать в комнате!

 Malleswari30 мар. 2018 г., 16:31
[player play], я получаю эту ошибку Нет известного метода класса для селектора 'играть'
 Jonny25 мая 2017 г., 11:48
В скором времени:NSNotification.Name.AVAudioSessionRouteChange

Это лучший учебник по этой проблеме: (хорошо работает и на iOS7)

http://www.techotopia.com/index.php/Detecting_when_an_iPhone_Headphone_or_Docking_Connector_is_Unplugged_(iOS_4)

Ваш ответ на вопрос