Внедрение и устранение неисправностей Фоновый звук в iOS

Есть много вопросов, связанных с воспроизведением фоновой музыки в iOS на StackOverflow. Никто не может полностью изучить все краевые дела, цель этот вопрос должен быть последним словом в фоновом звуковом вопросе о Иос

Определения и допущения

Весь код, вопросы и примеры относятся к .

"background" . Состояние, в которое приложение вводится, когда пользователь нажимает кнопку "домой" или кнопку питания (поэтому устройства отображают экран блокировки). Приложение можно также использовать в фоновом режиме, используя многозадачный коммутатор или жесты многозадачности на iPad.

"audio" - Аудио воспроизводится с использованием AudioQueue (включая AVAudioPlayer)

Необходимые условия

Как я понимаю, есть 2 требования к приложению для воспроизведения аудио в фоновом режиме.

  • Установите UIBackgroundModes в audio в Info.plist
  • [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];

Требования

В моем случае используется относительно длинный звук в фоновом режиме (музыка). Есть потенциально сотни треков, и приложение будет воспроизводить их последовательно. Можно считать, что звук будет проигрываться бесконечно.

Приложение будет обрабатывать прерывания, приостанавливая воспроизведение.

Вопросы

У меня был смешанный успех:

[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:...];

Разрешение воспроизведения звука в фоновом режиме. Но я смущен, если это необходимо и как оно отличается:

[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];

Пограничные случаи

  • Перерывы. Если вы зарегистрируетесь, чтобы получать уведомления о прерываниях звука (телефонные звонки и т.д.), Став делегатом AVAudioPlayer. Например, если вы приостанавливаете или останавливаете свой звук, когда прерывание начинается и возобновляется, когда оно заканчивается, ваше приложение приостановлено, если прерывание превышает 10 минут (максимальное время, разрешенное для выполнения фоновых задач)?

  • Симулятор остановит звук при вызове Lock или Home при использовании:

    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
    

Однако это работает на устройстве. Это известная проблема?

Ответы

Ответ 1

У меня есть опыт работы с фоновым режимом GPS и фоновым звуком. Это не совсем то же самое, что и ваша ситуация (вы хотите воспроизвести длинный звуковой файл, и я играю короткие сообщения), но вот что я могу вам сказать:

  • beginBackgroundTaskWithExpirationHandler Этот селектор имеет одну цель при вызове в фоновом режиме: избегайте приложению возвращаться в приостановленное состояние, в котором больше не может быть вызван код (вы "заморожены" ). Поэтому до тех пор, пока вы вызывали beginBackgroundTaskWithExpirationHandler и до того, как вы завершили свою долговременную задачу с помощью beginBackgroundTaskWithExpirationHandler, вы используете процессор и потребляете аккумулятор.
    Я действительно сомневаюсь, что игра в фоновом режиме должна использовать батарею iPhone, как если бы она запускала приложение, поэтому я сомневаюсь, что beginBackgroundTaskWithExpirationHandler действительно участвует в вашем потоке.

  • Симулятор: не полагайтесь на симулятор: он не полностью реализует фоновые режимы. Фактически, когда вы нажимаете кнопку "домой", ваше приложение уходит в фоновом режиме, но на этом этапе вы все равно сможете выполнить код в своем приложении. Через некоторое время ваше приложение будет приостановлено (= заморожено), и ваше исполнение кода будет приостановлено, чтобы сохранить батарею. Это приостановленное состояние никогда не будет происходить на симуляторе.

  • Перерывы. Это не зависит от вас, чтобы приостановить/возобновить воспроизведение при поступлении телефонного звонка. Платформа отвечает за это, и вы можете просто отреагировать на это с помощью AVAudioSessionDelegate. Тем не менее, вы можете повлиять на то, как ваш сеанс будет взаимодействовать с другими звуковыми звуками, установив свойство на ваш сеанс аудио (см. kAudioSessionProperty_OverrideCategoryMixWithOthers, например). Таким образом, поток больше: вы описываете, как ваш аудио-сеанс должен взаимодействовать с остальной системой, система будет смешивать звуки в соответствии с этим, и если ваш сеанс будет прерван, вы будете уведомлены с помощью AVAudioSessionDelegate.

Надеюсь, что это поможет.

Ответ 2

Я использовал ниже код для управления устройством -

[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];

Используется для регистрации регистра для прослушивания пульта дистанционного управления.  После этого удалите его -

[[UIApplication sharedApplication] endReceivingRemoteControlEvents];
[self resignFirstResponder];

сделать приложение canBecomeFirstResponder -

- (BOOL)canBecomeFirstResponder {
    return YES;
}

Используется метод делегата для управления iPhone, например, воспроизведение и пауза, а doble нажмите на домашнюю кнопку

- (void)remoteControlReceivedWithEvent:(UIEvent *)event {
    //if it is a remote control event handle it correctly
    if (event.type == UIEventTypeRemoteControl) {
        if (event.subtype == UIEventSubtypeRemoteControlPlay) {
           [audioPlayer play];
            NSLog(@"play");
        } else if (event.subtype == UIEventSubtypeRemoteControlPause) {
           [audioPlayer stop];
             NSLog(@"pause");
        } else if (event.subtype == UIEventSubtypeRemoteControlTogglePlayPause) {
            NSLog(@"toggle");
        }
    }
}