Решение ниже
Я работаю над работающим приложением, которое дает инструкции за кадром в начале каждого упражнения. Он работает по назначению, когда устройство активно, но не работает, когда телефон заблокирован. [Текущий звук продолжается, но не воспроизводится в будущем.]
Вопрос Как я могу начать воспроизведение закадрового голоса, когда iPhone пользователя заблокирован.
В настоящее время я отслеживаю тренировку, используя Timer.scheduledTimer для двух таймеров, которые я показываю [текущая активность и общая тренировка]. Когда таймер достигает заранее заданного времени ближе к концу одного действия, воспроизводится голос за кадром, чтобы представить следующее действие. Срабатывание таймера запускает звук, и я считаю, что проблема в этом. Я могу приостанавливать тренировку, пропускать разделы, и все работает нормально - пока устройство не заблокируется.
Если при нажатии кнопки "Домой" или блокировке iPhone воспроизводится закадровый голос, он продолжает воспроизводиться должным образом. Проблема в том, что таймер не срабатывает, поэтому следующая озвучка [скажем, через 90 секунд] никогда не воспроизводится.
В некоторых ответах и комментариях, которые я прочитал, говорится, что эта функция просто невозможна в iOS. Приложение Couch to 5k https://itunes.apple.com/gb/app/one-you-couch-to-5k/id1082307672?mt=8 использует эту функцию, поэтому я знаю, что этого можно достичь, но я просто не знаю, как они " повторю это. [Это будет специальный участник, который загрузит его, чтобы понять, что я имею в виду :)]
Из поиска SO Я прочитал много сообщений, в которых говорится, что Timer или NSTimer не могут работать, когда приложение находится в фоновом режиме или телефон заблокирован. Любые сообщения, в которых говорится, что это может работать, старые и основаны на iOS4 / 5.
Я читал о предложениях использовать тишину и, по сути, иметь один длинный аудиофайл. Хотя это создало бы некоторые новые проблемы для пропуска разделов тренировки, я также читал комментарии, в которых говорится, что такое поведение не пройдет тестирование Apple для приложения для AppStore. Третий недостаток в том, что размер моего аудиофайла увеличится.
Вариант, который я видел, - это локальные уведомления, однако я еще не видел примера того, который используется для воспроизведения звука за кадром, когда приложение находится в фоновом режиме.
Как я могу достичь той же функциональности, что и приложение Couch to 5k?
Спасибо
Ответ 1 · рейтинг 1 · Steve Hancocks
Хорошо, я разработал решение для воспроизведения звуковых подсказок пользователю в течение 30-минутной тренировки, даже если iPhone заблокирован или приложение работает в фоновом режиме. Приложение было отправлено и одобрено для размещения в AppStore.
Чтобы приложение работало должным образом, я использую 2 AVAudioPlayers; один воспроизводит закадровый голос, другой - 15-минутную дорожку тишины [так как это отдельная дорожка и просто без звука, это низкий качество .mp3 и только добавление 900 КБ к размеру приложения]. 15 минут намного превышают любой интервал между озвучкой, так что это отлично работает.
Когда пользователь начинает упражнение, воспроизводится первая звуковая подсказка. С этого момента, пока пользователь не остановит упражнение, в фоновом режиме будет воспроизводиться звук. Поскольку воспроизводится фоновый звук, таймер продолжает работать.
Когда закадровый голос заканчивается, вызывается AVAudioPlayerDelegate метод audioPlayerDidFinishPlaying. С помощью этого метода я сбрасываю свойства звука [я вскоре объясню почему], создаю экземпляр своего беззвучного AVAudioPlayer и начинаю проигрывать 15-минутный трек молчания. Воспроизведение другой дорожки с использованием этого метода делегата означает, что в фоновом звуке нет реального прерывания, поэтому приложение остается в рабочем состоянии. Когда приложение "живо", таймер продолжает обратный отсчет. Когда приходит время наложения голоса, таймер вызывает метод, который сбрасывает категорию аудио, создает экземпляр моего голоса за кадром AVAudioPlayer и воспроизводит голос за кадром. Этот процесс повторяется до финального озвучивания. Когда это завершится, тишина больше не воспроизводится, и приложение может быть безопасно отключено.
Закадровый голос должен заглушать музыку пользователей [уменьшает громкость музыки, чтобы звук был отчетливо слышен]. Беззвучный звук не должен этого делать, музыка должна продолжать играть на полной громкости. Поскольку оба AVAudioPlayer используют AVAudioSession.sharedInstance, я обнаружил, что мне пришлось деактивировать sharedInstance, сбросить свойства с .duckOthers или без него, а затем повторно активировать sharedInstance перед созданием моего AVAudioSession. Это дало мне желаемый результат. Постоянный фоновый звук, который заглушает музыку пользователей только при воспроизведении голоса за кадром.
do{
try AVAudioSession.sharedInstance().setActive(false)
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: [.interruptSpokenAudioAndMixWithOthers, .duckOthers])
try AVAudioSession.sharedInstance().setActive(true)
} catch{
print(error.localizedDescription)
}
Я знаю, что некоторые говорили, что Apple не разрешает беззвучный звук, однако в этом случае беззвучный звук воспроизводится только во время тренировки. Как только он завершится, приложение может прекратить работу, тем самым не поддерживая работу приложения дольше, чем необходимо.