Есть некоторые, казалось бы, похожие вопросы уже на SO, но после нескольких часов поиска и экспериментов с моим кодом я не смог найти четкий ответ. Самое близкое, что я мог найти, это this answer, который ссылается на «известную ошибку» 4 года назад, но не уточняет, как ее решить.Резюме AVAudioPlayer после телефонного звонка не работает
У меня есть класс audioPlayer, который воспроизводит аудиофайл с AVAudioPlayer и слушает AVAudioSessionDelegate
методы beginInterruption
и endInterruption
. Я знаю, что endInterruption
не гарантируется, поэтому я сохраняю логическое значение в beginInterruption
и обрабатываю перезапуск воспроизведения звука в applicationDidBecomeActive
.
Все это работает отлично, как ожидалось, если телефон принимает вызов, а пользователь отклоняет его или позволяет перейти на голосовую почту. Как только мое приложение вернется в активное состояние, воспроизведение звука возобновится.
Вот где я получаю странное поведение: Если пользователь отвечает вызов, когда они вешают все кажется работать, как ожидалось, но звук не выходит либо через наушники или громкоговорители.
Я могу проверить, что звук технически играет, печатая его громкость и текущее время каждую секунду, но звук не выходит.
Если я жду 20-40 секунд, звук внезапно прорезается и становится слышимым, как если бы он молча играл в фоновом режиме.
После дополнительной отладки я заметил, что AVAudioSession.sharedInstance().secondaryAudioShouldBeSilencedHint
остается true
за эти 20-40 секунд молчания, прежде чем внезапно перейти на false
и позволить звуку воспроизвести.
Я подписался на AVAudioSessionSilenceSecondaryAudioHintNotification
, чтобы увидеть, если я мог бы обнаружить это изменение, но оно никогда не вызывается, даже когда .secondaryAudioShouldBeSilencedHint
изменяется от true
к false
.
Я даже попробовал AVAudioSession.sharedInstance().setActive(true)
в методе, который возобновляет воспроизведение звука, но поведение не изменилось.
Наконец, я попытался установить таймер для задержки возобновления в течение 10 секунд после applicationDidBecomeActive
, но поведение не изменилось.
Итак, почему кажется, что телефонный звонок не освобождает управление аудиозаписью до моего приложения?
Спасибо, что посмотрели!
Код:
установки AVAudioSession в init()
:
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.handleAudioHintChange), name: AVAudioSessionSilenceSecondaryAudioHintNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.handleAudioInterruption), name: AVAudioSessionInterruptionNotification, object: nil)
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, withOptions: AVAudioSessionCategoryOptions.MixWithOthers)
print("AVAudioSession Category Playback OK")
do {
try AVAudioSession.sharedInstance().setActive(true, withOptions: .NotifyOthersOnDeactivation)
print("AVAudioSession is Active")
} catch let error as NSError {
print(error.localizedDescription)
}
} catch let error as NSError {
print(error.localizedDescription)
}
обработчики уведомлений:
///////////////////////////////////
// This never gets called :(//////
func handleAudioHintChange(notification: NSNotification) {
print("audio hint changed")
}
///////////////////////////////////
func handleAudioInterruption(notification: NSNotification) {
if notification.name != AVAudioSessionInterruptionNotification || notification.userInfo == nil{
return
}
if let typeKey = notification.userInfo [AVAudioSessionInterruptionTypeKey] as? UInt,
let type = AVAudioSessionInterruptionType(rawValue: typeKey) {
switch type {
case .Began:
print("Audio Interruption Began")
NSUserDefaults.standardUserDefaults().setBool(true, forKey:"wasInterrupted")
case .Ended:
print("Audio Interuption Ended")
}
}
}
App Делегат: функция
func applicationDidBecomeActive(application: UIApplication) {
if(NSUserDefaults.standardUserDefaults().boolForKey("wasInterrupted")) {
audioPlayer.resumeAudioFromInterruption()
}
}
Перезагрузка:
// This works great if the phone call is declined
func resumeAudioFromInterruption() {
NSUserDefaults.standardUserDefaults().removeObjectForKey("wasInterrupted")
do {
try AVAudioSession.sharedInstance().setActive(true)
print("AVAudioSession is Active")
} catch let error as NSError {
print(error.localizedDescription)
}
thisFunctionPlaysMyAudio()
}
Эй, спасибо за ответ. Я рад, что это может быть ошибка, а не только я сумасшедший. К сожалению, я уверен, что я также попытался отложить неудачу. Я дважды проверю и повторю попытку на этой неделе и дам вам знать, как это происходит ... –
любые обновления по этому вопросу? –
Пока нет, извините. Я полностью намерен пересмотреть это, но в списке есть другие вещи, которые мы решили расставить приоритеты. Я прокомментирую здесь, как только у меня появится возможность взглянуть. –