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.

Foi útil?

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.

http://developer.apple.com/library/ios/#samplecode/mixerhost/listings/classes_mixerhostviewcontroller_m.html

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top