在 iOS 8 上捕获音量增大/减小按钮的最简洁方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28193626/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 04:33:58  来源:igfitidea点击:

Cleanest way of capturing volume up/down button press on iOS 8

iosios8volume

提问by Ricardo Sanchez-Saez

What's the best/cleanest way of capturing volume up/down button presses on iOS 8?

iOS 8上捕获音量增大/减小按钮的最佳/最干净的方法是什么?

Ideally I'd like to capture the keypress and also prevent the system volume from changing (or at the very least, prevent the volume change HUD from showing).

理想情况下,我想捕获按键并防止系统音量发生变化(或者至少,防止音量变化 HUD 显示)。



There are some old answers going around which use deprecated methods and don't seem to work at all on iOS 8. This iOS 8 specific onedidn't work either.

有一些旧答案使用不推荐使用的方法,并且似乎在iOS 8 上根本不起作用。这个iOS 8 特定的也不起作用。

This RBVolumeButtonsopen source class doesn't seem to work on iOS 8 either.

这个RBVolumeButtons开源类似乎也不适用于 iOS 8。

回答by Mohammed Elrashidy

For Swift you can use next code in your viewController class:

对于 Swift,您可以在 viewController 类中使用下一个代码:

let volumeView = MPVolumeView(frame: CGRectMake(-CGFloat.max, 0.0, 0.0, 0.0))
self.view.addSubview(volumeView)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(volumeChanged(_:)), name: "AVSystemController_SystemVolumeDidChangeNotification", object: nil)

Then add this function

然后添加这个功能

func volumeChanged(notification: NSNotification) {

     if let userInfo = notification.userInfo {
        if let volumeChangeType = userInfo["AVSystemController_AudioVolumeChangeReasonNotificationParameter"] as? String {
            if volumeChangeType == "ExplicitVolumeChange" {
                // your code goes here
            }
        }
    }
}

This code detect the explicit volume change action by the user, as if you didn't check of the explicit action, this function will be automatically called periodically.

此代码检测用户的显式音量更改操作,如果您没有检查显式操作,则会定期自动调用此函数。

This code don't prevent the system volume change

此代码不会阻止系统音量更改

回答by MFP

First add AVFoundationand MediaPlayerFrameworkand then you can use below code to detect up/down button press,

首先添加AVFoundationMediaPlayer Framework,然后您可以使用以下代码检测向上/向下按钮按下,

-(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"]) {        
      float volumeLevel = [[MPMusicPlayerController applicationMusicPlayer] volume];
      NSLog(@"volume changed! %f",volumeLevel);
  }
}

回答by ingconti

for swift 3: (remember to add: import MediaPlayer.. )

对于 swift 3: (记得添加: import MediaPlayer.. )

    override func viewDidLoad() {
        super.viewDidLoad()

        let volumeView = MPVolumeView(frame: CGRect(x: 0, y: 40, width: 300, height: 30))
        self.view.addSubview(volumeView)
//      volumeView.backgroundColor = UIColor.red
        NotificationCenter.default.addObserver(self, selector: #selector(volumeChanged(notification:)),
                                               name: NSNotification.Name(rawValue: "AVSystemController_SystemVolumeDidChangeNotification"),
                                               object: nil)
    }


    func volumeChanged(notification: NSNotification) {

        if let userInfo = notification.userInfo {
            if let volumeChangeType = userInfo["AVSystemController_AudioVolumeChangeReasonNotificationParameter"] as? String {
                if volumeChangeType == "ExplicitVolumeChange" {
                    // your code goes here
                }
            }
        }
    }

....

....

回答by Terry

Objective-C version (using notifications):

Objective-C 版本(使用通知):

#import <MediaPlayer/MPVolumeView.h>
#import <AVFoundation/AVFoundation.h>

@interface ViewController () {
    UISlider *volumeViewSlider;
}

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self startTrackingVolumeChanges];
}

- (void)dealloc
{
    [self stopTrackingVolumeChanges];
}

#pragma mark - Start Tracking Volume Changes

- (void)startTrackingVolumeChanges
{
    [self setupVolumeViewSlider];
    [self addObserver];
    [self activateAudioSession];
}

- (void)setupVolumeViewSlider
{
    MPVolumeView *volumeView = [[MPVolumeView alloc] init];
    for (UIView *view in [volumeView subviews]) {
        if ([view.class.description isEqualToString:@"MPVolumeSlider"]) {
            volumeViewSlider = (UISlider *)view;
            break;
        }
    }
}

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

- (void)activateAudioSession
{
    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    [audioSession setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:nil];
    NSError *error;
    BOOL success = [audioSession setActive:YES error:&error];
    if (!success) {
        NSLog(@"Error activating audiosession: %@", error);
    }
}

#pragma mark - Observing Volume Changes

- (void)volumeChanged:(NSNotification *)notification
{
    NSString *volumeChangeType = notification.userInfo[@"AVSystemController_AudioVolumeChangeReasonNotificationParameter"];
    if ([volumeChangeType isEqualToString:@"ExplicitVolumeChange"]) {
        float volume = volumeViewSlider.value;
        NSLog(@"volume = %f", volume);
    }
}

#pragma mark - Stop Tracking Volume Changes

- (void)stopTrackingVolumeChanges
{
    [self removeObserver];
    [self deactivateAudioSession];
    volumeViewSlider = nil;
}

- (void)removeObserver
{
    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"AVSystemController_SystemVolumeDidChangeNotification" object:nil];
}

- (void)deactivateAudioSession
{
    dispatch_async(dispatch_get_main_queue(), ^{
        NSError *error;
        BOOL success = [[AVAudioSession sharedInstance] setActive:NO error:&error];
        if (!success) {
            NSLog(@"Error deactivating audiosession: %@", error);
        }
    });
}

@end

回答by Gary Riches

Ah ok, see the Audio Session Services References for more information. You need to start an audio session with AudioSessionInitialize and then make it active with AudioSessionSetActive, listen for changes in the volume with AudioSessionAddPropertyListener and pass a callback that has type AudioSessionPropertyListener.

好的,请参阅音频会话服务参考以获取更多信息。您需要使用 AudioSessionInitialize 启动音频会话,然后使用 AudioSessionSetActive 使其处于活动状态,使用 AudioSessionAddPropertyListener 侦听音量变化并传递类型为 AudioSessionPropertyListener 的回调。

This web site has a good write up: http://fredandrandall.com/blog/2011/11/18/taking-control-of-the-volume-buttons-on-ios-like-camera/

这个网站写得很好:http: //fredandrandall.com/blog/2011/11/18/taking-control-of-the-volume-buttons-on-ios-like-camera/

回答by samwize

This is a 2 part answers, and they are independent, in Swift 5.

这是一个 2 部分的答案,它们在Swift 5 中是独立的。

To listen to the volume trigger event,

监听音量触发事件,

import MediaPlayer

// Observe in eg. viewDidLoad
let volumeChangedSystemName = NSNotification.Name(rawValue: "AVSystemController_SystemVolumeDidChangeNotification")
NotificationCenter.default.addObserver(self, selector: #selector(volumeChanged), name: volumeChangedSystemName, object: nil)

@objc private func volumeChanged(notification: NSNotification) {
    guard
        let info = notification.userInfo, 
        let reason = info["AVSystemController_AudioVolumeChangeReasonNotificationParameter"] as? String,
        reason == "ExplicitVolumeChange" else { return }

    // Handle it
}

To hide the system volume control,

要隐藏系统音量控制,

// Add the view but not visible
let volumeView = MPVolumeView(frame: CGRect(x: -CGFloat.greatestFiniteMagnitude, y: 0, width: 0, height: 0))
view.addSubview(volumeView)