【问题标题】:How to programmatically sense the iPhone mute switch?如何以编程方式感知 iPhone 静音开关?
【发布时间】:2010-09-22 04:47:57
【问题描述】:

我似乎无法在 SDK 中找到如何以编程方式感知 iPhone 上的静音按钮/开关。当我的应用播放背景音乐时,它会正确响应音量按钮,而无需我遵循任何代码,但是,当我使用静音开关时,它只会继续播放。

如何测试静音的位置?

(注意:我的程序有自己的静音开关,但我希望物理开关覆盖它。)

【问题讨论】:

    标签: ios audio avaudiosession


    【解决方案1】:

    谢谢,摩根大通。实际上,您提供的链接会导致正确答案(最终。;)为了完整性(因为 S.O. 应该是快速答案的来源!)...

    // "Ambient" makes it respect the mute switch
    // Must call this once to init session
    if (!gAudioSessionInited)
    {
        AudioSessionInterruptionListener    inInterruptionListener = NULL;
        OSStatus    error;
        if ((error = AudioSessionInitialize (NULL, NULL, inInterruptionListener, NULL)))
        {
            NSLog(@"*** Error *** error in AudioSessionInitialize: %d.", error);
        }
        else
        {
            gAudioSessionInited = YES;
        }
    }
    
    SInt32  ambient = kAudioSessionCategory_AmbientSound;
    if (AudioSessionSetProperty (kAudioSessionProperty_AudioCategory, sizeof (ambient), &ambient))
    {
        NSLog(@"*** Error *** could not set Session property to ambient.");
    }
    

    【讨论】:

    • 如果我之后记录环境值,无论我是否静音,我总是会返回 1634558569。有什么想法吗?
    • “不起作用”怎么办?你做了什么?你期望会发生什么?相反,发生了什么?如果您提供更多信息,我会尝试更新我的答案。谢谢!
    【解决方案2】:

    我回答了一个类似的问题here (link)。相关代码:

     -(BOOL)silenced {
         #if TARGET_IPHONE_SIMULATOR
             // return NO in simulator. Code causes crashes for some reason.
             return NO;
         #endif
    
        CFStringRef state;
        UInt32 propertySize = sizeof(CFStringRef);
        AudioSessionInitialize(NULL, NULL, NULL, NULL);
        AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state);
        if(CFStringGetLength(state) > 0)
                return NO;
        else
                return YES;
    
        }
    

    【讨论】:

    • 正是我想要的。谢谢皮里普利!
    • 这在插入耳机时不起作用。无论静音开关如何,音频路由的 AudioSessionGetProperty 都会返回“耳机”。
    • 但是插入耳机时静音开关是否打开有关系吗?音频仍然从耳机中播放,是吗?在我看来,静音开关的目的是让别人的电话静音,而不是你自己。戴上耳机时遵守它并不重要(imo)。这似乎是苹果公司通过退回“耳机”所采取的立场
    • 不再适用于 iOS 5。stackoverflow.com/questions/6901363/…
    • 无赖!不是唯一在 iOS5 中长期不再工作的东西...... ;)
    【解决方案3】:

    如果您不在环境模式下,其他答案(包括接受的答案)中的某些代码可能无法工作,在这种模式下静音开关受到尊重。

    我编写了下面的例程来切换到环境,读取开关,然后返回到我的应用程序中需要的设置。

    -(BOOL)muteSwitchEnabled {
    
    #if TARGET_IPHONE_SIMULATOR
        // set to NO in simulator. Code causes crashes for some reason.
        return NO;
    #endif
    
    // go back to Ambient to detect the switch
    AVAudioSession* sharedSession = [AVAudioSession sharedInstance];
    [sharedSession setCategory:AVAudioSessionCategoryAmbient error:nil];
    
    CFStringRef state;
    UInt32 propertySize = sizeof(CFStringRef);
    AudioSessionInitialize(NULL, NULL, NULL, NULL);
    AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state);
    
    BOOL muteSwitch = (CFStringGetLength(state) <= 0);
    NSLog(@"Mute switch: %d",muteSwitch);
    
    // code below here is just restoring my own audio state, YMMV
    _hasMicrophone = [sharedSession inputIsAvailable];
    NSError* setCategoryError = nil;
    
    if (_hasMicrophone) {
    
        [sharedSession setCategory: AVAudioSessionCategoryPlayAndRecord error: &setCategoryError];
    
        // By default PlayAndRecord plays out over the internal speaker.  We want the external speakers, thanks.
        UInt32 ASRoute = kAudioSessionOverrideAudioRoute_Speaker;
        AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,
                                 sizeof (ASRoute),
                                 &ASRoute
                                 );
    }
    else
        // Devices with no mike don't support PlayAndRecord - we don't get playback, so use just playback as we don't have a microphone anyway
        [sharedSession setCategory: AVAudioSessionCategoryPlayback error: &setCategoryError];
    
    if (setCategoryError)
        NSLog(@"Error setting audio category! %@", setCategoryError);
    
    return muteSwitch;
    }
    

    【讨论】:

      【解决方案4】:

      为了找出静音开关的状态音量控制我写了这两个函数。如果您希望在用户尝试创建音频输出之前警告他们,这些是理想的选择。

      -(NSString*)audioRoute
      {
          CFStringRef state;
          UInt32 propertySize = sizeof(CFStringRef);
          OSStatus n = AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state);
          if( n )
          {
              // TODO: Throw an exception
              NSLog( @"AudioSessionGetProperty: %@", osString( n ) );
          }
      
          NSString *result = (NSString*)state;
          [result autorelease];
          return result;
      }
      
      -(Float32)audioVolume
      {
          Float32 state;
          UInt32 propertySize = sizeof(CFStringRef);
          OSStatus n = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareOutputVolume, &propertySize, &state);
          if( n )
          {
              // TODO: Throw an exception
              NSLog( @"AudioSessionGetProperty: %@", osString( n ) );
          }
          return state;
      }
      

      【讨论】:

        【解决方案5】:
        -(BOOL)isDeviceMuted
        {
         CFStringRef state;
         UInt32 propertySize = sizeof(CFStringRef);
         AudioSessionInitialize(NULL, NULL, NULL, NULL);
         AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state);
         return (CFStringGetLength(state) > 0 ? NO : YES);
        }
        

        【讨论】:

        • (CFStringGetLength(state) > 0 ? NO : YES) 与 (CFStringGetLength(state)
        • @simpleBob 如何检测 iphone 静音按钮的值。 (例如,如果 iphone 静音开关处于打开位置(处于静音状态)如何检测静音值)。
        • @Yuvaraj.M 这就是这个问题的意义所在。选择您最喜欢的答案;)例如,您可以只运行上面的方法,如果设备静音,则返回 YES。
        • @simpleBob 感谢您的回复。很抱歉打扰。它适用于所有ios吗?它在我的 ios5 中不起作用?。
        【解决方案6】:

        我遵循了这里的一般理论并使它起作用 http://inforceapps.wordpress.com/2009/07/08/detect-mute-switch-state-on-iphone/

        这里是一个回顾:播放一个简短的无声声音。时间玩多久。如果静音开关打开,声音的播放将比声音本身短得多。我使用了 500 毫秒的声音,如果声音播放的时间少于这个时间,那么静音开关就打开了。我使用音频服务来播放无声的声音(它总是尊重静音开关)。这篇文章说你可以使用 AVAudioPlayer 来播放这个声音。如果您使用 AVAudioPlayer,我假设您需要设置 AVAudioSession 的类别以支持静音开关,但我没有尝试过。

        【讨论】:

          【解决方案7】:

          使用 Ambient 模式播放视频和使用 PlayAndRecord 模式在相机屏幕上录制视频,解决了我们案例中的问题。

          应用程序中的代码:didFinishLaunchingWithOptions:

          NSError *error = nil;
          [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:&error];
          [[AVAudioSession sharedInstance] setMode:AVAudioSessionModeVideoRecording error:&error];
          [[AVAudioSession sharedInstance] setActive:YES error:&error];
          

          cameraController 上 viewWillAppear 中的代码,如果你必须在你的应用中使用摄像头或录制

          [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
          

          cameraController上viewWillDisappear中的代码

          [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];
          

          使用这些行,我们的应用程序录制和播放视频和静音开关在 iOS8 和 iOS7 下都能完美运行!!!

          【讨论】:

          • 你能帮帮我吗,我的应用程序中有 voip 通话功能,当用户接到电话时,我必须播放音乐/铃声。即使应用程序处于后台模式,我也想播放此铃声。如果我使用“AVAudioSessionCategoryPlayAndRecord”,它就不能使用静音开关,如果我使用“AVAudioSessionCategoryAmbient”,它就不会在后台播放。请给我建议以实现这两种情况。
          【解决方案8】:

          对于斯威夫特

          以下框架在设备中完美运行

          https://github.com/akramhussein/Mute

          只需使用 pod 安装或从 Git 下载

          pod 'Mute'
          

          并像下面的代码一样使用

          import UIKit
          import Mute
          
          class ViewController: UIViewController {
          
              @IBOutlet weak var label: UILabel! {
                  didSet {
                      self.label.text = ""
                  }
              }
          
              override func viewDidLoad() {
                  super.viewDidLoad()
          
                  // Notify every 2 seconds
                  Mute.shared.checkInterval = 2.0
          
                  // Always notify on interval
                  Mute.shared.alwaysNotify = true
          
                  // Update label when notification received
                  Mute.shared.notify = { m in
                      self.label.text = m ? "Muted" : "Not Muted"
                  }
          
                  // Stop after 5 seconds
                  DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
                      Mute.shared.isPaused = true
                  }
          
                  // Re-start after 10 seconds
                  DispatchQueue.main.asyncAfter(deadline: .now() + 10.0) {
                      Mute.shared.isPaused = false
                  }
              }
          
          }
          

          【讨论】:

            【解决方案9】:

            奥利,

            相信您可以在这里找到问题的答案:

            https://devforums.apple.com/message/1135#1135

            我假设您可以访问 Apple.com 上的开发者论坛 :)

            【讨论】:

            • 笑吧!快速回顾:“AudioSessionSetProperty 将 AudioCategory 设置为 Ambient”(我相信谈论发布软件是可以的……)谢谢!
            • 这条评论不是很有帮助。您至少可以从您发布的链接中发布报价吗?
            • 死链接和“仅链接”帖子无论如何都不是很有帮助。
            猜你喜欢
            • 1970-01-01
            • 2014-04-01
            • 1970-01-01
            • 1970-01-01
            • 2012-04-18
            • 1970-01-01
            • 2014-04-29
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多