2012-03-12 13 views
10

¿Hay alguna notificación que pueda escuchar que me diga cuándo se ha cambiado el volumen de un iPhone hasta?Detectar botón de volumen del iPhone Arriba ¿Presiona?

Conozco el AVSystemController_SystemVolumeDidChangeNotification, pero es esencial que la notificación solo se active cuando el volumen se haya subido, no hacia arriba o hacia abajo.

En segundo lugar, ¿cómo puedo ocultar la vista translúcida que aparece cuando se presiona el botón de subir volumen, mostrando el volumen del sistema? Cámara + ha implementado esto.

Respuesta

17

No hay una forma documentada de hacerlo, pero puede utilizar esta solución. Regístrese para la notificación AVSystemController_SystemVolumeDidChangeNotification y agregue un MPVolumeView que evitará que aparezca la vista de volumen del sistema.

MPVolumeView *volumeView = [[MPVolumeView alloc] initWithFrame:CGRectMake(-100, 0, 10, 0)]; 
[volumeView sizeToFit]; 
[self.view addSubview:volumeView]; 

Y no se olvide de iniciar una sesión de audio

AudioSessionInitialize(NULL, NULL, NULL, NULL); 
AudioSessionSetActive(true); 

En este caso, el MPVolumeView se oculta para el usuario.

Como comprobar si se ha presionado volumen hacia arriba o hacia abajo, sólo tienes que tomar el volumen de la aplicación actual

float volumeLevel = [[MPMusicPlayerController applicationMusicPlayer] volume]; 

y compararlo con el nuevo volumen después de que el botón se ha pulsado en función de notificación

Si no' t desea hacerlo por ti mismo, hay una caída en la clase disponible en gitHub

https://github.com/blladnar/RBVolumeButtons

+0

Una cosa que he notado sobre el uso de este método es que si tengo otra aplicación reproduciendo música de fondo (o potencialmente si ya estabas reproduciendo música en la aplicación donde estabas haciendo la detección), eso dejaría de recibir notificaciones y los botones de volumen volverían simplemente a cambiar el volumen de la música que se reproduce en el fondo =/ – Will

+0

'[[MPMusicPlayerController applicationMusicPlayer] volume]' ha quedado en desuso desde iOS 7. – JaredH

+0

Cualquier alternativa para la propiedad "volumen" para silenciar .... – Javeed

36

Si desea una n caso se puede registrar un detector en la propiedad "OutputVolume":

- (void)viewWillAppear:(BOOL)animated { 

    AVAudioSession* audioSession = [AVAudioSession sharedInstance]; 

    [audioSession setActive:YES error:nil]; 
    [audioSession addObserver:self 
        forKeyPath:@"outputVolume" 
         options:0 
         context:nil]; 
} 

-(void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 

    if ([keyPath isEqual:@"outputVolume"]) { 
     NSLog(@"volume changed!"); 
    } 
} 
+5

He visto tantos lugares en stackoverflow y este es el único que usa métodos y cadenas no desaprobados para hacer esto. – ShayanK

+10

El problema con esta solución es que si el outputVolume ya es máximo y presionan el botón +, la devolución de llamada no ocurre. –

+0

esta solución es muy buena, pero ray es correcta :(¿es posible restablecer el valor de forma programática en 0? – donmarkusi

3

He resuelto este problema mediante la adición propio objetivo/acción para UISlider colocado dentro MPVolumeView. Por lo tanto, es posible detectar eventos de cambio de volumen y determinar qué botón se presionó. Aquí está github repo con la implementación de este enfoque. Funciona bien con iOS 7 y superior, sin advertencias de desaprobación y sin rechazo por parte de Apple.

0

el fin de distinguir la acción de volumen: EN LUGAR DE (en guardia observeValue)

temp != 0.5 

USO por sólo volumen hasta

temp > 0.5 

y sólo detectar el volumen abajo:

temp < 0.5 

Esta solución a continuación se imprimirá si se presiona el volumen hacia arriba o hacia abajo.

import AVFoundation 
import MediaPlayer 

override func viewDidLoad() { 
    super.viewDidLoad() 
    let volumeView = MPVolumeView(frame: CGRect.zero) 
    for subview in volumeView.subviews { 
    if let button = subview as? UIButton { 
     button.setImage(nil, for: .normal) 
     button.isEnabled = false 
     button.sizeToFit() 
    } 
    } 
    UIApplication.shared.windows.first?.addSubview(volumeView) 
    UIApplication.shared.windows.first?.sendSubview(toBack: volumeView) 
} 

override func viewWillAppear(_ animated: Bool) { 
    super.viewWillAppear(animated) 
    AVAudioSession.sharedInstance().addObserver(self, forKeyPath: "outputVolume", options: NSKeyValueObservingOptions.new, context: nil) 
    do { try AVAudioSession.sharedInstance().setActive(true) } 
    catch { debugPrint("\(error)") } 
} 

override func viewDidDisappear(_ animated: Bool) { 
    super.viewDidDisappear(animated) 
    AVAudioSession.sharedInstance().removeObserver(self, forKeyPath: "outputVolume") 
    do { try AVAudioSession.sharedInstance().setActive(false) } 
    catch { debugPrint("\(error)") } 
} 

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { 
    guard let key = keyPath else { return } 
    switch key { 
    case "outputVolume": 
     guard let dict = change, let temp = dict[NSKeyValueChangeKey.newKey] as? Float, temp != 0.5 else { return } 
     let systemSlider = MPVolumeView().subviews.first { (aView) -> Bool in 
     return NSStringFromClass(aView.classForCoder) == "MPVolumeSlider" ? true : false 
     } as? UISlider 
     systemSlider?.setValue(0.5, animated: false) 
     guard systemSlider != nil else { return } 
     debugPrint("Either volume button tapped.") 
    default: 
     break 
    } 
} 
Cuestiones relacionadas