【问题标题】:System Volume Change Observer not working on iOS 15系统音量变化观察器在 iOS 15 上不起作用
【发布时间】:2021-09-15 20:37:40
【问题描述】:

我使用以下代码来检测用户更改的系统音量。

NotificationCenter.default.addObserver(self, selector: #selector(volumeChanged), name: NSNotification.Name(rawValue: "AVSystemController_SystemVolumeDidChangeNotification"), object: nil)

当我更新到 iOS 15 时,我发现这段代码不起作用,但对于任何以前的 iOS 版本它都可以。

我也使用了addObserver 函数,但没关系。

这是 iOS 15 的错误吗?如果是,我该怎么做才能修复它。

谢谢:)

【问题讨论】:

    标签: swift volume ios15


    【解决方案1】:

    我挂钩了 MPVolumeControllerSystemDataSource 的方法 _systemVolumeDidChange 并且在 iOS 15.0(至少 beta2) 通知名称已更改为 SystemVolumeDidChange 这是新的通知结构:

    {
        AudioCategory = "Audio/Video";
        Reason = ExplicitVolumeChange;
        SequenceNumber = 1069;
        Volume = 0;
    }
    

    有两点需要注意:

    1. iOS 15(至少在 beta2 中)的此通知即使按一次音量按钮也会被调用两次,但它们的 SequenceNumber 是相等的;
    2. 此通知回调不在主线程上。

    【讨论】:

      【解决方案2】:

      您正在执行的操作不受支持,因此如果它不适用于所有系统也就不足为奇了。正确记录的方法是在音频会话 outputVolume 属性上使用 KVO:https://developer.apple.com/documentation/avfaudio/avaudiosession/1616533-outputvolume

      【讨论】:

        【解决方案3】:

        尝试了 AdamWang 的回答后,我发现您需要创建并保留 MPVolumeView 的实例(但不需要添加到您的视图层次结构中),否则不会发出通知。

        【讨论】:

          【解决方案4】:

          在 iOS15 中,@"AVSystemController_SystemVolumeDidChangeNotification" 通知不再被调用。

          改为使用键值观察。 (扩展上面马特的回答)

          在您的 ViewController.m 文件中

          #import <AVFoundation/AVFoundation.h>
          #import <MediaPlayer/MediaPlayer.h>
          
          @interface ViewController : UIViewController
          {
              AVAudioSession *audioSession;
          }
          
          @end
          

          在您的 View Controller.m 文件中

          -(void)viewWillAppear:(BOOL)animated {
              [super viewWillAppear:animated];
          
              audioSession = [AVAudioSession sharedInstance];
              [audioSession setActive:YES error:nil];
              [audioSession addObserver:self forKeyPath:@"outputVolume" options:0 context:nil];
          
          }
          
          - (void)viewWillDisappear:(BOOL)animated
          {
              [super viewWillDisappear:animated]; 
          
              [audioSession removeObserver:self forKeyPath:@"outputVolume"];
          }
          
          
          - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
          
              CGFloat newVolume = audioSession.outputVolume;
              NSLog(@"newVolume: %f", newVolume);
          
                //if the volume gets to max or min observer won't trigger
              if (newVolume > 0.9 || newVolume < 0.1) {
                  [self setSystemVolume:0.5];
                  return;
              }
          }
          
            //set the volume programatically
          - (void)setSystemVolume:(CGFloat)volume {
              #pragma clang diagnostic push
              #pragma clang diagnostic ignored "-Wdeprecated-declarations"
              [[MPMusicPlayerController applicationMusicPlayer] setVolume:(float)volume];
              #pragma clang diagnostic pop
          }
          

          您可以使用移出屏幕的 MPVolumeView 隐藏音量滑块。

          Hide device Volume HUD view while adjusitng volume with MPVolumeView slider

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-01-13
            相关资源
            最近更新 更多