繁体   English   中英

如何检测iOS中音量的变化?

[英]how to detect the changes of volume in iOS?

我已经阅读了 stackOverFlow 和 gitHub 提供的很多解决方案,它们都对我不起作用。我尝试了以下两种方式:

  1. 使用音频会话
override func viewWillAppear(_ animated: Bool) {
        let audioSession = AVAudioSession.sharedInstance()
        do {
            try audioSession.setActive(true, options: [])
        } catch {
            print("error")
        }
        // this print shows, got the current volume.
        //but what I need is the notification of the change of volume
        print("view will appear ,this volume is \(audioSession.outputVolume)")
        audioSession.addObserver(self,
                                 forKeyPath: "outputVolume",
                                 options: [.new],
                                 context: nil)
    }

override class func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
        if keyPath == "outputVolume"{
            let audioSession = AVAudioSession.sharedInstance()
            let volume = audioSession.outputVolume
            //this print doesn't shows up
            print("observed volume is \(volume)")
        }
    }
  1. 使用通知
    override func viewWillAppear(_ animated: Bool) {
        NotificationCenter.default.addObserver(self, selector: #selector(observed(_:)), name: Notification.Name(rawValue: "AVSystemController_SystemVolumeDidChangeNotification"), object: nil)
    }

    @objc func observed(_ notification: Notification){
        print("observed")
    }

顺便说一句,我正在使用模拟器(iPhone11,iOS13.1),Xcode 版本是 11.1

尝试使用以下内容:

import UIKit
import MediaPlayer
import AVFoundation
  
class ViewController: UIViewController {
  
    private var audioLevel: Float = 0.0

    deinit {
        audioSession.removeObserver(self, forKeyPath: "outputVolume")
    }
      
    override func viewDidLoad() {
        super.viewDidLoad()
    }
      
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        listenVolumeButton()
    }
      
    func listenVolumeButton() {
          
        let audioSession = AVAudioSession.sharedInstance()
        do {
            try audioSession.setActive(true, options: [])
            audioSession.addObserver(self, forKeyPath: "outputVolume",
                                     options: NSKeyValueObservingOptions.new, context: nil)
            audioLevel = audioSession.outputVolume
        } catch {
            print("Error")
        }
    }
      
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
        if keyPath == "outputVolume" {
            let audioSession = AVAudioSession.sharedInstance()
            if audioSession.outputVolume > audioLevel {
                print("Hello")
                audioLevel = audioSession.outputVolume
            }
            if audioSession.outputVolume < audioLevel {
                print("Goodbye")
                audioLevel = audioSession.outputVolume
            }
            if audioSession.outputVolume > 0.999 {
                (MPVolumeView().subviews.filter { NSStringFromClass($0.classForCoder) == "MPVolumeSlider" }.first as? UISlider)?.setValue(0.9375, animated: false)
                audioLevel = 0.9375
            }
              
            if audioSession.outputVolume < 0.001 {
                (MPVolumeView().subviews.filter { NSStringFromClass($0.classForCoder) == "MPVolumeSlider"}.first as? UISlider)?.setValue(0.0625, animated: false)
                audioLevel = 0.0625
            }
        }
    }
}

希望对你有帮助!

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

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

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

let volume = audioSession.outputVolume

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

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)
   }
}

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

func stopObservingVolumeChanges() {
    audioSession.removeObserver(self, forKeyPath: Observation.VolumeKey, 
context: &Observation.Context)
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM