首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在iOS上获取音频音量级别和音量更改通知?

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

Stack Overflow用户
提问于 2010-09-06 11:58:50
回答 10查看 62.9K关注 0票数 60

我正在编写一个非常简单的应用程序,在按下按钮时播放声音。因为当设备被设置为静音时,这个按钮没有多大意义,所以当设备的音频音量为零时,我想禁用它。(随后,当音量再次增大时,重新启用它。)

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

所有这些都是在使用said按钮的我的ViewController中实现的。我已经用运行iPhone 4.0.1和4.0.2的iOS 4以及运行4.0.1的iPhone 3G进行了测试。使用iOS SDK4.0.2和llvm1.5构建。(使用gcc或llvm并不能改善任何情况。)在构建实现过程中没有任何问题,也没有错误或警告。静态分析仪也很高兴。

以下是我迄今所尝试过的,但都没有成功。

根据苹果的音频服务文档,我应该为kAudioSessionProperty_CurrentHardwareOutputVolume注册一个kAudioSessionProperty_CurrentHardwareOutputVolume,它的工作方式如下:

代码语言:javascript
运行
复制
// Registering for Volume Change notifications
AudioSessionInitialize(NULL, NULL, NULL, NULL);
returnvalue = AudioSessionAddPropertyListener (

kAudioSessionProperty_CurrentHardwareOutputVolume ,
      audioVolumeChangeListenerCallback,
      self
);

returnvalue0,这意味着注册回调是有效的。

可悲的是,当我按下设备上的音量按钮、耳机的按键或按响器静音开关时,我的函数audioVolumeChangeListenerCallback就永远回不来了。

当使用完全相同的代码来注册kAudioSessionProperty_AudioRouteChange (在WWDC视频、开发人员文档和许多站点上作为类似的示例项目使用)时,我实际上在更改音频路由时得到了回调(通过插入/拔出耳机或对接设备)。

一个名为Doug的用户打开了一个名为iPhone volume changed event for volume already max的线程,在该线程中,他声称他成功地使用了这种方式(除非卷实际上不会改变,因为它已经设置为最大值)。不过,这对我不管用。

我尝试过的另一种方式是像这样在NSNotificationCenter注册。

代码语言:javascript
运行
复制
// sharedAVSystemController 
AudioSessionInitialize(NULL, NULL, NULL, NULL);
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver:self
                                         selector:@selector(volumeChanged:) 
                                             name:@"AVSystemController_SystemVolumeDidChangeNotification" 
                                           object:nil];

这应该会将任何volumeChanged更改通知我的方法SystemVolume,但实际上它并没有这样做。

因为共同的信念告诉我,如果一个人太努力地用可可来实现某件事情,那就是做了一些根本错误的事情,我希望在这里错过一些东西。很难相信有什么简单的方法可以达到目前的音量水平,但我还没能通过使用苹果的文档、示例代码、谷歌( Google )、苹果开发者论坛( Apple Developer Forum)或通过观看WWDC 2010视频来找到一个。

EN

回答 10

Stack Overflow用户

发布于 2011-06-24 18:25:05

您是否有可能对volumeChanged:方法做了错误的签名?这对我起了作用,把它扔到了我的应用程序中:

代码语言:javascript
运行
复制
- (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
}

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

票数 70
EN

Stack Overflow用户

发布于 2015-03-20 16:03:08

这里一些答案所使用的AudioSession API在iOS 7中已被废弃,取而代之的是AVAudioSession,它为系统范围的输出卷公开了一个outputVolume属性。在卷发生变化时,可以使用KVO接收通知,如文档中所指出的:

A值在0.0到1.0之间,0.0表示最小卷,1.0表示最大卷。

系统宽的输出卷只能由用户直接设置;要在应用程序中提供卷控制,请使用MPVolumeView类。

您可以通过使用键值观察来观察此属性值的更改。

您需要确保应用程序的音频会话是活动的,这样才能工作:

代码语言:javascript
运行
复制
let audioSession = AVAudioSession.sharedInstance()
do {
    try audioSession.setActive(true)
    startObservingVolumeChanges()
} catch {
    print(“Failed to activate audio session")
}

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

代码语言:javascript
运行
复制
let volume = audioSession.outputVolume

或者,我们可以收到这样的变更通知:

代码语言:javascript
运行
复制
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)
    }
}

不要忘记在被释放之前停止观察:

代码语言:javascript
运行
复制
func stopObservingVolumeChanges() {
    audioSession.removeObserver(self, forKeyPath: Observation.VolumeKey, context: &Observation.Context)
}
票数 56
EN

Stack Overflow用户

发布于 2012-02-04 03:41:01

代码语言:javascript
运行
复制
-(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;
}

这应该能让你达到当前的音量水平。1是最大音量,0是无音量。注意:不需要显示UI元素就可以工作。还请注意,当前的音量级别相对于耳机或扬声器(这意味着,这两个音量级别是不同的,这将使您无论该设备目前使用的是什么。这并不能回答您关于接收卷更改通知的问题。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3651252

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档