iOS 4: Controles remotos para áudio de fundo
-
27-09-2019 - |
Pergunta
No momento, estou tentando configurar áudio de fundo para um aplicativo que estou desenvolvendo para iOS 4. O aplicativo não tem um jogador de música dedicado viewController
, no entanto, diferentemente de outros aplicativos de áudio em segundo plano, como a Pandora, o que torna a tarefa um pouco mais confusa.
Eu defini o apropriado Info.plist
configurações corretamente e ter um AVAudioPlayer
Objeto no meu delegado de aplicativo, que é acessível de todos os lugares. Quando o usuário toca uma música, eu substituo o AVAudioPlayer
Com um novo inicializado com a música e toca. Tudo isso funciona muito bem, exceto agora que não tenho idéia de como apoiar eventos de controle remoto.
Com base na documentação da Apple, eu tenho isso:
- (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;
}
}
A questão é: onde eu coloco isso? A documentação da Apple parece sugerir que isso deve entrar em algum controlador de exibição em algum lugar, mas meu aplicativo tem muitos controladores de exibição e controladores de navegação. Onde quer que eu tento colocar isso, por algum motivo tocar o botão Toggle Play/Pause nos controles remotos da bandeja multitarefa, ou faz com que a música pare por um momento e depois não esteja, ou de alguma forma faz com que a música toque duas vezes.
Solução 2
Encontrei algumas soluções para receber eventos globais de controle remoto nos fóruns de desenvolvedores da Apple após um pouco de pesquisa.
Uma maneira é subclasse UIWindow
e substituir seu remoteControlReceivedWithEvent:
.
O segundo, talvez melhor caminho é subclasse UIApplication
e substituir sendEvent:
. Dessa forma, você pode interceptar todos os eventos de controle remoto e manipulá -los lá globalmente, e não ter outros respondedores lidam com eles mais tarde na cadeia de resposta.
- (void)sendEvent:(UIEvent *)event {
if (event.type == UIEventTypeRemoteControl) {
// Handle event
}
else
[super sendEvent:event];
}
Outras dicas
Os exemplos de documentação são um pouco enganosos, mas não há necessidade de subclassem nada em qualquer lugar. O local correto para colocar remoteControlReceivedWithEvent: está no delegado do aplicativo, pois permanece na cadeia de respondedores, independentemente de o aplicativo estar em primeiro plano ou não. Além disso, os eventos de controle remoto de início/final devem basear -se se você realmente precisa dos eventos, não na visibilidade de alguma visão aleatória.
O segundo método não funcionou para mim, sendEvent
nunca foi chamado. No entanto, o primeiro método funcionou bem (subclassificação UIWindow
).
Eu lutei com este por um tempo e nenhuma das respostas acima funcionou. O bug do meu código, e espero que isso ajude alguém a ler isso, foi que eu tinha a audiosação definida para se misturar com outras pessoas. Você quer ser o player de áudio em primeiro plano para obter eventos de controle remoto. Verifique se você tem código incorreto como este:
[[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];
E remova o AudiSessionsetProperty ou altere a dosetProperty para 1.
Não há necessidade de subclasse a janela ou encaminhar eventos. Basta lidar com isso do seu controlador de exibição principal. Consulte o exemplo do misturador de áudio (mixerhost) para obter detalhes.
Uma coisa que parece influenciar esse comportamento são as opções de categoria que você define para sua Avaudiossession usando o setCategory: WithOptions: Error: em vez de apenas setCategory: Error:. Em particular, a partir de tentativa e erro, parece que, se você definir a AvaudiosessionCategoryOptionMixwithothers, você não receberá eventos de controle remoto; Os controles agora de reprodução ainda controlarão o aplicativo iPod. Se você definir a AvaudiosessionCategoryOptionDuckothers, receberá eventos de controle remoto, mas parece que pode haver alguma ambiguidade em relação a qual aplicativo é controlado. Definir as categorias como 0 ou apenas chamando o setCategory: Erro: funciona melhor.