access ao programa para botões de volume do iPhone

Existe alguma maneira de se inscrever em events de imprensa de botões de volume?

Após as recentes rejeições da Apple

Não use isso. A Apple agora usa algum patch que rejeitaria seu aplicativo imediatamente se ele usa qualquer uma das APIs privadas – embora deva observar aqui que alguns aplicativos na App Store já usam isso e ainda estão lá!

A única maneira de fazer isso agora é ter um AVAudioPlayer preparado para jogar, mas não jogando ([player prepareToPlay]). Isso parece cuidar de ajustar o volume do aplicativo de acordo com os botões do agitador.

Não há outra maneira publicada atualmente para lidar com isso.

POR FAVOR, LEIA O NOTA ACIMA

Sim, use o MPVolumeView

MPVolumeView *volume = [[[MPVolumeView alloc] initWithFrame:CGRectMake(18.0, 340.0, 284.0, 23.0)] autorelease]; [[self view] addSubview:volume]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(volumeChanged:) name:@"AVSystemController_SystemVolumeDidChangeNotification" object:nil]; for (UIView *view in [volume subviews]){ if ([[[view class] description] isEqualToString:@"MPVolumeSlider"]) { volumeViewSlider = view; //volumeViewSlider is a UIView * object } } [volumeViewSlider _updateVolumeFromAVSystemController]; -(IBAction)volumeChanged:(id)sender{ [volumeViewSlider _updateVolumeFromAVSystemController]; } 

Isso lhe dará um controle deslizante (o mesmo usado no ipod), cujo valor será alterado de acordo com o volume do telefone.

Você receberá um aviso em tempo de compilation que a visualização pode não responder a _updateVolumeFromAVSystemControl, mas apenas ignorá-la.

Se você quer apenas receber as notifications, acho que é assim:

Por favor, corrija-me se estiver errado, mas não acredito que isso use qualquer API interna.

 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(volumeChanged:) name:@"AVSystemController_SystemVolumeDidChangeNotification" object:nil]; 

Detalhes deste evento estão aqui: http://www.cocoadev.com/index.pl?AVSystemController

As outras respostas aqui parecem ser baseadas neste hack: http://blog.stormyprods.com/2008/09/proper-usage-of-mpvolumeview-class.html que foi uma solução para um bug agora corrigido.

Mas tenho certeza que se tudo o que você quer fazer é obter a notificação, e não definir o volume do sistema, basta usar o centro de notifications como em qualquer outro evento !!

Esteja avisado: como a Apple adicionou a ação de aumento de volume à câmera, essa notificação não é enviada enquanto um UIImagePickerController estiver visível.

Se você está disposto a mergulhar na API privada, eu tenho um patch para o Wolf3d que adiciona exatamente a funcionalidade que você está procurando. Ele usa a class AVSystemController privada e alguns methods ocultos no UIApplication

OK,

Então eu vi suas soluções e não sei exatamente se a Apple vai rejeitar ou aceitar o uso do AVSystemController_SystemVolumeDidChangeNotification . Mas eu tenho um trabalho por aí.

Use o UISlider do MPVolumeView para registrar qualquer alteração no volume pelo hardware do iPhone como este

 MPVolumeView *volumeView = [[MPVolumeView alloc] initWithFrame:CGRectZero]; for (UIView *view in [volumeView subviews]) { if ([view.class.description isEqualToString:@"MPVolumeSlider"]){ self.volume_slider = (UISlider*)view; break; } } [volumeView sizeToFit]; #THIS IS THE MAIN LINE. ADD YOUR CALLBACK TARGET HERE [self.volume_slider addTarget:self action:@selector(volumeListener:) forControlEvents:UIControlEventValueChanged]; [self addSubview:volumeView]; [volumeView setAlpha:0.0f]; -(void)volumeListener:(NSNotification*)notification { #UPDATE YOUR UI ACCORDING OR DO WHATEVER YOU WANNA DO. #YOU CAN ALSO GET THE SOUND STEP VALUE HERE FROM NOTIFICATION. } 

Deixe-me saber se isso ajuda alguém.

A maneira mais fácil e funcionalmente completa de fazer isso que eu encontrei em estudar todas as fonts mencionadas acima e em outros tópicos é: JPSVolumeButtonHandler (Eu não estou envolvido além de ser um usuário. Mas muito obrigado às pessoas responsáveis!)

EDIT: Release 1.0.2 veio com algumas alterações / aprimoramentos significativos. Deixarei minha resposta anterior para 1.0.1 abaixo da dobra.

Eu coloquei uma class de wrapper de amostra que você pode implementar como está, ou usar para aprender o uso esperançosamente apropriado de JPSVolumeButtonHandler em um repository separado do Github bem rápido aqui .

Veja como o wrapper deve ser usado (adicionarei isso ao repository assim que chegar a ele):

  1. A class singleton tem dois sinalizadores: isInUse e isOn . isInUse destina-se a ser definido em algum tipo de configurações gerais de aplicativos e alterna o suporte de botão de modo geral e desativado. Portanto, independentemente de quaisquer outros valores na class, se isso for false nada acontecerá quando o usuário pressionar um botão de volume e a implementação garantir, tanto quanto possível, manter as coisas limpas e não afetar desnecessariamente o nível de volume do sistema. (Leia a edição mencionada no README para saber o que pode acontecer, quando o suporte de botões é ligado pela primeira vez.) O isOn deve ser true exatamente isOn o botão for necessário. Você pode ligá-lo e desligá-lo sem considerar o valor presente de isInUse .

  2. Em qualquer visualização que você inicializar a ação que deveria acontecer quando um botão de volume for pressionado, defina a ação da seguinte forma:

    PhysicalButton.shared.action = {/ * fazer alguma coisa * /}

A ação tem type () -> Void . Até você inicializar a ação, nada vai quebrar. Apenas nada vai acontecer. Essa funcionalidade defensiva era importante para mim, pois a exibição que usa o suporte ao botão de volume só seria criada depois que o suporte ao botão fosse configurado.

Para ver as coisas em ação, você pode fazer o download do aplicativo que estou usando de forma rápida e gratuita. As configurações manipulam “Suporte ao botão físico” em geral. A visualização principal do Cronômetro é a que realmente liga o manuseio dos botões ao entrar na visualização, e ao desligá-la. Se você encontrar a hora, você também encontrará uma nota importante em Configurações> Guia do Usuário> Opção: Suporte a Botão Físico:

Em circunstâncias excepcionais, o aplicativo pode não ter a chance de alternar corretamente o manuseio do botão de volume fora da exibição do cronômetro …

Eu adicionarei a nota completa ao Github README.md. Sinta-se à vontade para adaptar e reutilizar, se for relevante no seu caso.

As circunstâncias não são realmente tão excepcionais e eu não entendi totalmente o que está errado. Quando o usuário mata o aplicativo (ou você simplesmente interrompe o aplicativo no Xcode) enquanto os botões de volume estão ativados, o suporte ao botão físico pode não ser removido corretamente do sistema operacional. Assim, você pode acabar com duas instâncias de manipulador interno, das quais apenas um tem controle. Então, cada toque de botão resulta em duas ou mais chamadas para a rotina de ação. Meu wrapper tem algum código de guardião para evitar uma chamada muito rápida do botão. Mas isso é apenas uma solução parcial. A correção precisa ir para o manipulador subjacente, que lamentavelmente ainda tenho muito pouca compreensão para tentar consertar as coisas sozinho.


VELHO, PARA 1.0.1:

Em particular, meu interesse estava em uma solução Swift. O código está no Objective-C. Para salvar alguém alguma pesquisa, isso é tudo que fiz usando Cocoapods (para manequins como eu):

  1. Adicione o pod 'JPSVolumeButtonHandler' ao podfile
  2. Execute a pod install na linha de comando
  3. Adicione #import ao arquivo de header de ponte
  4. Configure retornos de chamada para os botões de volume para cima e para baixo da seguinte forma:

     let volumeButtonHandler = JPSVolumeButtonHandler( upBlock: { log.debug("Volume up button pressed...") // Do something when the volume up button is pressed... }, downBlock: { log.debug("Volume down button pressed...") // Do something else for volume down... }) 

É isso aí. O resto é opcional.


No meu caso, eu queria ativar botões físicos sobrepostos com botões virtuais na canvas apenas para visualizações selecionadas, enquanto bloqueava o mínimo possível das funções normais dos botões (para que o usuário pudesse executar música em segundo plano e ajustar seu volume no resto do aplicativo muito bem). Eu acabei com uma maioria de singleton class da seguinte forma:

 class OptionalButtonHandler { static var sharedInstance: OptionalButtonHandler? private var volumeButtonHandler: JPSVolumeButtonHandler? = nil private let action: () -> () var enabled: Bool { set { if !enabled && newValue { // Switching from disabled to enabled... assert(volumeButtonHandler == nil, "No leftover volume button handlers") volumeButtonHandler = JPSVolumeButtonHandler(upBlock: { log.debug("Volume up button pressed...") self.action() }, downBlock: { log.debug("Volume down button pressed...") self.action() }) } else if enabled && !newValue { log.debug("Disabling physical button...") // The other way around: Switching from enabled to disabled... volumeButtonHandler = nil } } get { return (volumeButtonHandler != nil) } } /// For one-time initialization of this otherwise singleton class. static func initSharedInstance(action: () -> ()) { sharedInstance = OptionalButtonHandler(action: action) } private init(action: () -> ()) { self.action = action } } 

Há apenas uma ação comum para os botões de volume para cima e para baixo aqui. O initSharedInstance() era necessário, porque minha ação incluía referências a um elemento da interface do usuário (uma visualização) que só seria configurado em algum ponto dependente do usuário após o lançamento do aplicativo.

Uma vez configurado assim:

 OptionalButtonHandler.initSharedInstance({ // ...some UI action }) 

Ativar / desativar seletivamente simplesmente assim:

 OptionalButtonHandler.sharedInstance!.enabled = true // (false) 

(Observe que minha lógica de código garante que .enabled nunca seja acessado antes de initSharedInstance() .)

Estou executando o Xcode 7.3 e o iOS 9.3.2 no dispositivo de teste (obrigatório!).

Ansioso para aprender como a Apple se sente sobrecarregando seus preciosos botões de volume. Pelo menos meu aplicativo garante ser minimamente invasivo e o uso de botões realmente faz sentido. Não é um aplicativo de câmera, mas aplicativos comparáveis ​​usaram botões de volume físico antes (menos bem uniformes).