iOS 音量变化监听 (媒体音量和铃声音量)

143 阅读1分钟

媒体音量监听

1.通过音频会话

缺点

  • 监听开启, 会占用音频会话, 导致其他播放声音的app停止播放。
  • 切换到后台后失效, 需要在切换回前台时, 再重新注册
class VolumeListener: NSObject {

    private var audioSession: AVAudioSession!
    private var volumeObservation: NSKeyValueObservationprivate var volumeDidChange: (_ volume:Float) -> () //音量变化通知函数

    init(volumeDidChange: @escaping (_ volume:Float) -> ()) {
        self.volumeDidChange = volumeDidChange
        super.init()
        setupAudioSession()
    }

    private func setupAudioSession() {
        audioSession = AVAudioSession.sharedInstance()
        do {
            try audioSession.setActive(true, options: [])
        } catch {
            print("Failed to activate audio session: \(error)")
            return
        }
        startObservingVolume()
    }

    private func startObservingVolume() {
        volumeObservation = audioSession.observe(\.outputVolume, options: [.new]) { [weak self] (audioSession, _) in
            let currentVolume = audioSession.outputVolume
            self?.volumeDidChange(currentVolume)
        }
    }

    func stopObservingVolume() {
        volumeObservation = nil
    }

    deinit {
        stopObservingVolume()
    }
}

⚠️ 在系统 设置->声音与触感->打开用按钮调整, 这个时候监听不到音量变化

2.通过 MPVolumeView

解决方案: 隐藏 系统的 MPVolumeView 视图

let volumeView = MPVolumeView(frame: CGRect(x: -500, y: -500, width: 0, height: 0))
volumeView.showsVolumeSlider = false
volumeView.sizeToFit()

if let slider = volumeView.subviews.first as? UISlider {
    slider.addTarget(self, action: #selector(volumeChanged(_:)), for: .valueChanged)
    systemVolumeSlider = slider
    currentVolume = Int(slider.value * 100)
}

view.addSubview(volumeView)

⚠️ 在系统 设置->声音与触感->打开用按钮调整, 这个时候监听不到音量变化

3. 通过监听通知 SystemVolumeDidChange

NotificationCenter.default.addObserver(self, selector: #selector(volumeChanged1(noti:)), name: NSNotification.Name(rawValue: "SystemVolumeDidChange"), object: nil)

缺点:音量变化回调, 会执行两次