Detectar el botón de volumen del iPhone hacia arriba ¿Presionar?
-
12-12-2019 - |
Pregunta
¿Hay alguna notificación que pueda escuchar y que me avise cuando se sube el volumen de un iPhone? arriba?
sé sobre el AVSystemController_SystemVolumeDidChangeNotification
, pero es esencial que la notificación solo se active cuando se haya subido el volumen, 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 para subir el volumen, mostrando el volumen del sistema? Cámara+ ha implementado esto.
Solución
No existe una forma documentada de solucionarlo, pero puede utilizar esta solución alternativa.Regístrese para AVSystemController_SystemVolumeDidChangeNotification
notificación y agregar un MPVolumeView
lo que evitará que aparezca la vista del volumen del sistema.
MPVolumeView *volumeView = [[MPVolumeView alloc] initWithFrame:CGRectMake(-100, 0, 10, 0)];
[volumeView sizeToFit];
[self.view addSubview:volumeView];
Y no olvides iniciar una sesión de audio.
AudioSessionInitialize(NULL, NULL, NULL, NULL);
AudioSessionSetActive(true);
En este caso, el MPVolumeView
está oculto para el usuario.
En cuanto a verificar si se presionó subir o bajar el volumen, simplemente tome el volumen de la aplicación actual
float volumeLevel = [[MPMusicPlayerController applicationMusicPlayer] volume];
y compararlo con el nuevo volumen después de presionar el botón en la devolución de llamada de notificación
Si no quieres hacerlo solo, hay una clase sin cita previa disponible en github.
Otros consejos
Si desea un evento, puede registrar un oyente 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!");
}
}
Resolví este problema agregando mi 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á repositorio de github con la implementación de este enfoque.Funciona bien con iOS 7 y superior, sin advertencias de desuso ni rechazo por parte de Apple.
Para distinguir la acción del volumen: EN LUGAR DE (en observarValue guard)
temp != 0.5
USAR solo para subir el volumen
temp > 0.5
y solo detecta volumen bajo:
temp < 0.5
Esta solución a continuación se imprimirá si se presiona subir o bajar el volumen.
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
}
}