Уведомление о прерывании IOS AVAudioSession не работает должным образом

Я хочу знать, когда мой AVAudioRecorder недоступен (например, когда музыка начинает воспроизводиться).

Поскольку audioRecorderEndInterruption будет устаревшим с iOS 9, я сосредоточен на уведомлении прерывания AVAudioSession (но ни один из них не работает как ожидалось).

Проблема в том, что уведомление о прерывании никогда не вызывается, если приложение было и остается на переднем плане, когда происходит прерывание.

Например: пользователь запускает и останавливает воспроизведение музыки, не перемещая приложение в фоновом режиме.

Чтобы обнаружить любые прерывания, которые я использую:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioSessionWasInterrupted:) name:AVAudioSessionInterruptionNotification object:nil];
...
- (void)audioSessionWasInterrupted:(NSNotification *)notification {
    if ([notification.name isEqualToString:AVAudioSessionInterruptionNotification]) {
        NSLog(@"Interruption notification");

        if ([[notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey] isEqualToNumber:[NSNumber numberWithInt:AVAudioSessionInterruptionTypeBegan]]) {
            NSLog(@"InterruptionTypeBegan");
        } else {
            NSLog(@"InterruptionTypeEnded");
        }
    }
}

Я получаю InterruptionTypeBegan, как ожидалось, но InterruptionTypeEnded не вызывается, если приложение все еще находится на переднем плане (это означает, что он не будет вызываться, пока приложение не будет помещено в фоновом режиме и обратно на передний план).

Как я могу получать уведомление InterruptionTypeEnded, когда прерывание происходит, когда приложение находится на переднем плане?

Ответы

Ответ 1

Это распространенная проблема, затрагивающая любое приложение, использующее компоненты AV framework (то же самое относится к родным приложениям iOS).

Как объяснено в  документации по поводу прерывания звука, InterruptionTypeEnded должен применяться в упомянутом сценарии:

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

Однако он также утверждает, что InterruptionTypeEnded может вообще не вызываться:

Нет гарантии, что прерывание начала будет иметь прерывание конца.

Поэтому в упомянутом сценарии необходим другой подход.


Когда дело доходит до обработки перерывов в работе, проблема не будет длиться долго. iOS 9 эффективно предотвращает использование внешних источников звука во время вызова обработчика аудио приложения.

Способом обработки точной проблемы прерывания медиа может быть прослушивание MPMusicPlayerController playbackState, как показано в этом вопросе stackoverflow: Обнаружение, если музыка играет?.


Более прямой способ справиться с проблемой прерываний будет следующим:

Полностью заблокируйте внешние прерывания звука, повторно используя ваш аудиокомпонент во время InterruptionTypeBegan.

Или, указав индикацию пользовательского интерфейса, что внешний медиа-источник прервал сеанс аудио (например, неактивный микрофон).


Надеюсь,  придумает лучшее решение проблемы, но пока это даст вам некоторые варианты решения проблемы прерывания.

Ответ 3

Я пробую это и обнаруживаю, что InterruptionTypeEnded может вызывать после паузы в музыке в каком-то приложении, но другие не вызываются при паузе.

Мое решение - обновить пользовательский интерфейс, чтобы остановить запись информации о пользователе и выполнить некоторые связанные работы, такие как работа с файлами. Когда прерывание заканчивается, активная AVAudioSession, , если не имеет ошибки, запустите новую запись.

Если вы хотите присоединиться к файлу до и после прерывания, ответ на этот вопрос: AVAudioRecorder записывает только аудио после перерыва, может быть вам полезен.