Erkennen Sie, dass die Lautstärketaste des iPhone nach oben gedrückt wird?
-
12-12-2019 - |
Frage
Gibt es eine Benachrichtigung, die ich abhören kann und die mir mitteilt, wenn die Lautstärke eines iPhones gedreht wird? hoch?
Ich weiß davon AVSystemController_SystemVolumeDidChangeNotification
, aber es ist wichtig, dass die Benachrichtigung nur ausgelöst wird, wenn die Lautstärke erhöht wurde, nicht nach oben oder unten.
Zweitens: Wie kann ich die durchscheinende Ansicht ausblenden, die beim Drücken der Lauter-Taste erscheint und die Lautstärke des Systems anzeigt? Kamera+ hat dies umgesetzt.
Lösung
Es gibt keine dokumentierte Möglichkeit hierfür, aber Sie können diese Problemumgehung verwenden.Registrieren für AVSystemController_SystemVolumeDidChangeNotification
Benachrichtigung und fügen Sie eine hinzu MPVolumeView
Dadurch wird verhindert, dass die Systemvolume-Ansicht angezeigt wird.
MPVolumeView *volumeView = [[MPVolumeView alloc] initWithFrame:CGRectMake(-100, 0, 10, 0)];
[volumeView sizeToFit];
[self.view addSubview:volumeView];
Und vergessen Sie nicht, eine Audiositzung zu starten
AudioSessionInitialize(NULL, NULL, NULL, NULL);
AudioSessionSetActive(true);
In diesem Fall ist die MPVolumeView
bleibt dem Benutzer verborgen.
Um zu überprüfen, ob die Lautstärke erhöht oder verringert wurde, greifen Sie einfach auf die Lautstärke der aktuellen Anwendung zurück
float volumeLevel = [[MPMusicPlayerController applicationMusicPlayer] volume];
und vergleichen Sie es mit der neuen Lautstärke, nachdem die Taste im Benachrichtigungsrückruf gedrückt wurde
Wenn Sie es nicht alleine machen möchten, gibt es in Github einen Drop-in-Kurs
Andere Tipps
Wenn Sie ein Ereignis wünschen, können Sie einen Listener für die Eigenschaft „outputVolume“ registrieren:
- (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!");
}
}
Ich habe dieses Problem gelöst, indem ich ein eigenes Ziel/eine eigene Aktion für den darin platzierten UISlider hinzugefügt habe MPVolumeView
.So ist es möglich, Lautstärkeänderungsereignisse zu erfassen und festzustellen, welche Taste gedrückt wurde.Hier ist Github-Repo mit der Umsetzung dieses Ansatzes.Es funktioniert einwandfrei mit iOS 7 und höher, es gibt keine veralteten Warnungen und keine Ablehnung von Apple.
Zur Unterscheidung der Volumenwirkung: ANSTATT (im ObservValue Guard)
temp != 0.5
VERWENDEN nur um die Lautstärke zu erhöhen
temp > 0.5
und nur die Lautstärke erkennen:
temp < 0.5
Diese Lösung unten wird gedruckt, wenn entweder die Lautstärke erhöht oder verringert wird.
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
}
}