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 на пульте дистанционного управления многозадачного лотка приводит к тому, что песня просто приостанавливается на мгновение, а затем приостанавливается или каким-то образом заставляет песню проигрывать дважды.
Ответы
Ответ 1
Я нашел несколько решений для получения глобальных событий удаленного управления на форумах разработчиков Apple после небольшого поиска.
Один из способов заключается в подклассе UIWindow
и переопределении его remoteControlReceivedWithEvent:
.
Второй, возможно, более приятным способом является подкласс UIApplication
и переопределить sendEvent:
. Таким образом, вы можете перехватывать все события удаленного управления и обрабатывать их там по всему миру, а другие респондеры не будут обрабатывать их позже в цепочке ответчиков.
- (void)sendEvent:(UIEvent *)event {
if (event.type == UIEventTypeRemoteControl) {
// Handle event
}
else
[super sendEvent:event];
}
Ответ 2
Примеры документации немного вводят в заблуждение, но нет необходимости подклассифицировать что-либо в любом месте. Правильное место для размещения remoteControlReceivedWithEvent: находится в делетете приложения, так как оно остается в цепочке ответчиков независимо от того, находится ли приложение на переднем плане или нет. Кроме того, события начала и окончания приема и дистанционного управления должны основываться на том, действительно ли вам нужны события, а не на видимости какого-либо случайного вида.
Ответ 3
Второй метод не работал у меня, sendEvent
никогда не вызывался. Однако первый метод работал просто красиво (подклассификация UIWindow
).
Ответ 4
Я боролся с этим на какое-то время, и ни один из ответов выше не работал. Ошибка в моем коде, и я надеюсь, что это поможет кому-то прочитать это, было то, что у меня был набор AudioSession для смешивания с другими. Вы хотите быть аудиопроигрывателем переднего плана для получения событий дистанционного управления. Проверьте, есть ли код INCORRECT следующим образом:
[[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.
Ответ 5
Нет необходимости в подклассе событий Window или forward. Просто отрегулируйте его с основного контроллера. Подробнее см. В примере аудиомикшер (MixerHost).
http://developer.apple.com/LIBRARY/IOS/#samplecode/MixerHost/Listings/Classes_MixerHostViewController_m.html
Ответ 6
Документация объясняет это очень хорошо.
https://developer.apple.com/library/ios/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/Remote-ControlEvents/Remote-ControlEvents.html
Ответ 7
Одна вещь, которая, кажется, влияет на это поведение, - это любые параметры категории, которые вы задали для своего AVAudioSession, используя setCategory: withOptions: error: вместо просто setCategory: error:. В частности, из проб и ошибок, похоже, что если вы установите AVAudioSessionCategoryOptionMixWithOthers, вы не будете получать события дистанционного управления; теперь играющие элементы управления будут управлять iPod. Если вы установите AVAudioSessionCategoryOptionDuckOthers, вы получите события дистанционного управления, но похоже, что может быть какая-то неопределенность в отношении того, какое приложение контролируется. Установка categoryOptions в 0 или просто вызов setCategory: ошибка: работает лучше всего.