如何在iOS上获得音量级别和音量更改通知?

Mac*_*mon 56 iphone audio volume ios4 ios

我正在写一个非常简单的应用程序,按下按钮时会发出声音.由于当设备设置为静音时该按钮没有多大意义,我想在设备的音量为零时禁用它.(然后当音量再次升高时重新启用它.)

我正在寻找一种工作(和AppStore安全)方式来检测当前的音量设置,并在音量级别改变时获得通知/回调.我不想改变音量设置.

所有这些都是在我ViewController使用所述按钮的地方实现的.我用运行iOS 4.0.1和4.0.2的iPhone 4以及运行4.0.1的iPhone 3G测试了这个.使用iOS SDK 4.0.2和llvm 1.5构建.(使用gcc或llvm-gcc不能改进任何东西.)在构建实现​​任何一种方式时都没有问题,既没有错误也没有警告.静态分析仪也很开心.

这是我到目前为止所尝试的,都没有任何成功.

继苹果公司的音频服务的文件,我应该在注册AudioSessionAddPropertyListenerkAudioSessionProperty_CurrentHardwareOutputVolume应该像这样工作:

// Registering for Volume Change notifications
AudioSessionInitialize(NULL, NULL, NULL, NULL);
returnvalue = AudioSessionAddPropertyListener (

kAudioSessionProperty_CurrentHardwareOutputVolume ,
      audioVolumeChangeListenerCallback,
      self
);
Run Code Online (Sandbox Code Playgroud)

returnvalue是的0,这意味着注册回调有效.

可悲的是,audioVolumeChangeListenerCallback当我按下设备上的音量按钮,耳机响铃或翻转振铃静音开关时,我从未收到回调功能.

当使用完全相同的代码进行注册时kAudioSessionProperty_AudioRouteChange(用作WWDC视频中的类似示例项目,开发人员文档以及互联网上的众多站点)我实际上在更改音频路径时收到回调(通过插入/拔出耳机或对接设备).

一个名为Doug的用户打开了一个标题为iPhone卷改变事件的线程已经达到最大值,他声称他已成功使用这种方式(除非卷实际上没有因为已经设置为最大而改变).不过,它对我不起作用.

我尝试过的另一种方法就是NSNotificationCenter像这样注册.

// sharedAVSystemController 
AudioSessionInitialize(NULL, NULL, NULL, NULL);
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver:self
                                         selector:@selector(volumeChanged:) 
                                             name:@"AVSystemController_SystemVolumeDidChangeNotification" 
                                           object:nil];
Run Code Online (Sandbox Code Playgroud)

这应该通知我的方法volumeChanged有任何SystemVolume变化,但实际上并没有这样做.

由于共同的信念告诉我,如果一个人努力工作以实现与Cocoa的某些事情,那么我就会做一些根本错误的事情,我期待在这里错过一些东西.很难相信,有没有简单的方法获得当前的音量,但使用苹果的文档,示例代码,谷歌,苹果开发者论坛我一直没能找到一个或观看WWDC 2010条的视频.

San*_*ndy 67

你有没有机会为volumeChanged:方法签名错误?这对我有用,倾倒在我的appdelegate中:

- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [[NSNotificationCenter defaultCenter]
     addObserver:self
     selector:@selector(volumeChanged:)
     name:@"AVSystemController_SystemVolumeDidChangeNotification"
     object:nil];
}

- (void)volumeChanged:(NSNotification *)notification
{
    float volume =
    [[[notification userInfo]
      objectForKey:@"AVSystemController_AudioVolumeNotificationParameter"]
     floatValue];

    // Do stuff with volume
}
Run Code Online (Sandbox Code Playgroud)

我的volumeChanged:方法在每次按下按钮时都会被击中,即使音量没有因此而改变(因为它已经是最大/分钟).

  • 如果添加`MPVolumeView*slide = [MPVolumeView new];`以及`#import <MediaPlayer/MediaPlayer.h>,则可以正常工作 (7认同)
  • 是"AVSystemController_SystemVolumeDidChangeNotification"私有?因为如果这是可以让你的应用程序被拒绝. (5认同)
  • 添加一个不可见的MPVolumeView,它将工作. (3认同)

Stu*_*art 50

AudioSession此处某些答案使用的API自iOS 7起已被弃用.它被替换为AVAudioSession,它公开outputVolume了系统范围输出卷的属性.如文档中所指出的,使用KVO可以观察到当卷发生变化时接收通知:

值范围为0.0到1.0,其中0.0表示最小体积,1.0表示最大体积.

系统范围的输出量只能由用户直接设置; 要在您的应用程序中提供音量控制,请使用MPVolumeView类.

您可以使用键值观察来观察对此属性值的更改.

您需要确保应用程序的音频会话处于活动状态才能使其正常工作:

let audioSession = AVAudioSession.sharedInstance()
do {
    try audioSession.setActive(true)
    startObservingVolumeChanges()
} catch {
    print(“Failed to activate audio session")
}
Run Code Online (Sandbox Code Playgroud)

因此,如果您只需要查询当前系统卷:

let volume = audioSession.outputVolume
Run Code Online (Sandbox Code Playgroud)

或者我们可以收到类似变化的通知:

private struct Observation {
    static let VolumeKey = "outputVolume"
    static var Context = 0

}

func startObservingVolumeChanges() {
    audioSession.addObserver(self, forKeyPath: Observation.VolumeKey, options: [.Initial, .New], context: &Observation.Context)
}

override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
    if context == &Observation.Context {
        if keyPath == Observation.VolumeKey, let volume = (change?[NSKeyValueChangeNewKey] as? NSNumber)?.floatValue {
            // `volume` contains the new system output volume...
            print("Volume: \(volume)")
        }
    } else {
        super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context)
    }
}
Run Code Online (Sandbox Code Playgroud)

在被解除分配之前不要忘记停止观察:

func stopObservingVolumeChanges() {
    audioSession.removeObserver(self, forKeyPath: Observation.VolumeKey, context: &Observation.Context)
}
Run Code Online (Sandbox Code Playgroud)


Mik*_*ike 6

-(float) getVolumeLevel
{
    MPVolumeView *slide = [MPVolumeView new];
    UISlider *volumeViewSlider;

    for (UIView *view in [slide subviews]){
        if ([[[view class] description] isEqualToString:@"MPVolumeSlider"]) {
            volumeViewSlider = (UISlider *) view;
        }
    }

    float val = [volumeViewSlider value];
    [slide release];

    return val;
}
Run Code Online (Sandbox Code Playgroud)

这应该可以获得当前的音量水平.1是最大音量,0是无音量.注意:不需要显示UI元素才能使其生效.另请注意,当前音量级别与耳机或扬声器相关(意味着两个音量级别不同,这可以使您获得当前正在使用的设备.这不会回答有关接收音量变化时的通知的问题.


Kar*_*ten 4

您是否使用 AudioSessionSetActive 启动音频会话