iOS 4: Пульт дистанционного управления для фонового звука

В настоящее время я пытаюсь настроить фоновый звук для приложения, которое разрабатываю для iOS 4. Однако приложение не имеет специального музыкального проигрывателя viewController, однако, в отличие от других приложений для фонового звука, таких как Pandora, что немного усложняет задачу. более запутанный.

Я правильно установил Info.plist настройки, и в моем делегате приложения есть объект AVAudioPlayer, который доступен отовсюду. Когда пользователь воспроизводит песню, я заменяю AVAudioPlayer новым, инициализированным песней, и проигрываю ее. Все это отлично работает, за исключением того, что теперь я понятия не имею, как поддерживать события удаленного управления.

Основываясь на документации Apple, у меня есть это:

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
    [self becomeFirstResponder];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [[UIApplication sharedApplication] endReceivingRemoteControlEvents];
    [self resignFirstResponder];
}

- (BOOL)canBecomeFirstResponder {
    return YES;
}

- (void)remoteControlReceivedWithEvent:(UIEvent *)event {
    switch(event.subtype) {
        case UIEventSubtypeRemoteControlTogglePlayPause:
            if([iPhoneAppDelegate backgroundAudioPlayer].playing)
                [iPhoneAppDelegate pauseBackgroundAudioPlayer];
            else
                [iPhoneAppDelegate playBackgroundAudioPlayer];
            break;
    }
}

Дело в том, где мне это поставить? Документация Apple, похоже, предполагает, что это должно быть где-то в каком-то контроллере представления, но в моем приложении много контроллеров представления и контроллеров навигации. Куда бы я ни пытался поместить это, по какой-то причине нажатие кнопки Toggle Play / Pause на пульте дистанционного управления в области многозадачности либо заставляет песню просто приостанавливаться на мгновение, а затем приостанавливать ее, либо каким-то образом заставляет песню воспроизводиться дважды.


person Anshu Chimala    schedule 11.08.2010    source источник
comment
Как вы изменили кнопку воспроизведения / остановки на панели многозадачности ?!   -  person Arthur Neves    schedule 07.05.2011


Ответы (7)


Примеры документации немного вводят в заблуждение, но нет необходимости где-либо создавать подклассы. Правильное место для размещения remoteControlReceivedWithEvent: находится в делегате приложения, поскольку он остается в цепочке ответчика независимо от того, находится ли приложение на переднем плане или нет. Кроме того, начало / конец получения событий удаленного управления должно основываться на том, действительно ли вам нужны события, а не на видимости некоторого случайного представления.

person Brian Dam Pedersen    schedule 14.01.2012
comment
Совершенно верно. Чтобы получить полный контроль над удаленным управлением для вашего приложения (будь то передний план или фон), вам нужно вызвать beginReceivingRemoteControlEvents в application: didFinishLaunchingWithOptions :, но это еще не все. Ваш UIApplicationDelegate начинает получать события удаленного управления после того, как ваше приложение сообщает iOS, что оно воспроизводит трек - путем установки свойства MPNowPlayingInfoCenter nowPlayingInfo. - person HiveHicks; 30.03.2012
comment
Это действительно отличный ответ, я задержался на неделе. - person Khalid Usman; 10.07.2012
comment
Добавление remoteControlReceivedWithEvent: в делегат приложения просто не работает для меня; Мне пришлось создать подкласс UIWindow. - person JosephH; 19.07.2012
comment
Совет: remoteControlReceivedWithEvent не работал, пока я не удалил его дубликат из UIViewController. - person Shmidt; 17.08.2012
comment
Включение remoteControlReceivedWithEvent: в делегат приложения тоже не сработало для меня, пока я не понял, что мой делегат приложения (созданный из шаблона xcode еще в дни iOS2) является подклассом NSObject. Как только я переключил делегата своего приложения на подкласс UIResponder -remoteControlReceivedWithEvent: начал вызываться. - person hyperspasm; 07.09.2012
comment
Обновление: включение remoteControlReceivedWithEvent: в делегат приложения работает для меня только на iOS5, чтобы заставить все работать в iOS4, мне пришлось создать подкласс UIWindow. - person hyperspasm; 08.09.2012
comment
Просто чтобы обогатить ответ. В случае моего приложения с панелью вкладок на iOS6 размещение элемента управления событиями в контроллере панели вкладок работало правильно. Вместо этого в iOS7 мне пришлось переместить его в applicationDelegate, потому что я предполагаю, что что-то изменилось в том, как ОС управляет этим материалом. Теперь работает нормально. - person super; 29.09.2013
comment
Спасибо. Поместите remoteControlReceivedWithEvent: в делегат приложения, работает только у меня в iOS7 / iOS8. - person ziggear; 24.11.2014

После небольшого поиска я нашел пару решений для получения глобальных событий удаленного управления на форумах разработчиков Apple.

Один из способов - создать подкласс UIWindow и переопределить его remoteControlReceivedWithEvent:.

Второй, возможно, более удобный способ - создать подкласс UIApplication и переопределить sendEvent:. Таким образом, вы можете перехватывать все события удаленного управления и обрабатывать их там глобально, и никакие другие респонденты не будут обрабатывать их позже в цепочке респондентов.

- (void)sendEvent:(UIEvent *)event {
     if (event.type == UIEventTypeRemoteControl) {
          // Handle event
     }
     else
          [super sendEvent:event];
}
person Anshu Chimala    schedule 11.08.2010
comment
См. Мой комментарий к ответу Брайана Дама Педерсена - person HiveHicks; 31.03.2012
comment
Еще более удобный способ сделать это - добавить его в обычное приложение UIA в категории. - person hypercrypt; 03.05.2012
comment
Я бы порекомендовал ответ Брайана - person Mazyod; 30.06.2012

Второй способ у меня не сработал, sendEvent ни разу не вызвал. Однако первый метод работал хорошо (создание подкласса UIWindow).

person Stelian Iancu    schedule 19.12.2010
comment
Работает как шарм. Я хочу добавить, что beginReceivingRemoteControlEvents можно вызвать внутри делегата приложения для подписки на событие удаленного управления. - person Ben Affleck; 19.05.2011

Некоторое время я боролся с этим, и ни один из приведенных выше ответов не помог. Ошибка в моем коде, и я надеюсь, что это поможет кому-то, кто это прочитает, заключалась в том, что у меня был настроен AudioSession для микширования с другими. Вы хотите быть аудиоплеером переднего плана, чтобы получать события удаленного управления. Проверьте, есть ли у вас НЕПРАВИЛЬНЫЙ код вроде этого:

    [[AVAudioSession sharedInstance] setDelegate: self];
    [[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: nil];
    UInt32 doSetProperty = 0;
    AudioSessionSetProperty (
                             kAudioSessionProperty_OverrideCategoryMixWithOthers,
                             sizeof (doSetProperty),
                             &doSetProperty
                             );
    NSError *activationError = nil;
    [[AVAudioSession sharedInstance] setActive: YES error: &activationError];       

И удалите AudioSessionSetProperty или измените doSetProperty на 1.

person Sherwin Zadeh    schedule 29.05.2012

Нет необходимости создавать подклассы Window или пересылать события. Просто обработайте это с помощью основного контроллера представления. См. Подробности в примере Audio Mixer (MixerHost).

http://developer.apple.com/LIBRARY/IOS/#samplecode/MixerHost/Listings/Classes_MixerHostViewController_m.html

person slf    schedule 27.07.2011
comment
Дело в том, что ваш главный контроллер представления не всегда будет на экране, пока приложение переходит в фоновый режим, то есть он не станет первым респондентом, если на экране находится модальное окно. - person pablasso; 30.11.2011
comment
@pablasso может быть, в зависимости от приложения. Но не во всех случаях я с этим согласен. - person slf; 01.12.2011

Документация очень хорошо это объясняет. https://developer.apple.com/library/ios/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/Remote-ControlEvents/Remote-ControlEvents.html.

person Vladimir Shutyuk    schedule 04.09.2013

Одна вещь, которая, кажется, влияет на это поведение, - это любые параметры категории, которые вы устанавливаете для своего AVAudioSession с помощью setCategory: withOptions: error: вместо просто setCategory: error :. В частности, методом проб и ошибок выяснилось, что если вы установите AVAudioSessionCategoryOptionMixWithOthers, вы не получите событий удаленного управления; элементы управления, которые сейчас воспроизводятся, будут по-прежнему управлять приложением iPod. Если вы установите AVAudioSessionCategoryOptionDuckOthers, вы получите события удаленного управления, но похоже, что может быть некоторая двусмысленность относительно того, какое приложение контролируется. Установка categoryOptions на 0 или просто вызов setCategory: error: работает лучше всего.

person Jimmy Dee    schedule 21.09.2014