如何在设备静音时通过AVAudioSession播放系统音效?
解决方案:绕过静音播放系统音效
你的核心问题在于AudioServicesPlayAlertSound并不受AVAudioSession的playback类别控制——这个API属于系统音效服务,播放逻辑完全遵循系统静音开关状态,和AVAudioSession设置无关。要实现静音时也能播放,必须改用AVPlayer通过AVAudioSession播放对应的系统音效文件,步骤如下:
1. 获取SystemSoundID对应的音效文件URL
利用AudioServicesGetProperty可以通过SystemSoundID反向获取其对应的本地文件URL,这个方法是公开API,可安全用于上架应用:
private static func getSoundURL(for systemSoundID: SystemSoundID) -> URL? { var url: CFURL? let status = AudioServicesGetProperty( kAudioServicesPropertySystemSoundURL, UInt32(MemoryLayout<SystemSoundID>.size), &systemSoundID, nil, &url ) guard status == noErr, let soundURL = url else { return nil } return URL(cfURL: soundURL) }
2. 修改SoundManager用AVPlayer播放
通过AVAudioSession的playback类别确保音频不受静音开关影响,同时用AVPlayer加载获取到的音效文件:
import Foundation import AVFoundation struct SoundManager { static var audioPlayer: AVAudioPlayer? static func playSound(forSystemID systemSoundID: SystemSoundID) { let audioSession = AVAudioSession.sharedInstance() do { // 设置playback类别,允许与其他音频混音,不受静音开关控制 try audioSession.setCategory(.playback, mode: .default, options: .mixWithOthers) try audioSession.setActive(true, options: .notifyOthersOnDeactivation) // 获取目标音效的URL guard let soundURL = getSoundURL(for: systemSoundID) else { LogManager.logToFile("无法获取System Sound ID: \(systemSoundID)对应的音频URL") return } // 初始化并播放音频 audioPlayer = try AVAudioPlayer(contentsOf: soundURL) audioPlayer?.prepareToPlay() audioPlayer?.play() // 如需触觉反馈,单独调用系统震动API AudioServicesPlaySystemSound(kSystemSoundID_Vibrate) } catch { LogManager.logToFile("播放音频出错: \(error.localizedDescription)") } } private static func getSoundURL(for systemSoundID: SystemSoundID) -> URL? { var url: CFURL? let status = AudioServicesGetProperty( kAudioServicesPropertySystemSoundURL, UInt32(MemoryLayout<SystemSoundID>.size), &systemSoundID, nil, &url ) guard status == noErr, let soundURL = url else { return nil } return URL(cfURL: soundURL) } }
关键注意事项
playback类别是专门用于媒体播放的音频会话类别,默认不受设备静音开关影响(仅受媒体音量控制)。- 若需后台播放音频(导航APP通常需要),需在
Info.plist中添加UIBackgroundModes数组并包含audio项。 - 原
AudioServicesPlayAlertSound会同时触发音效和触觉反馈,改用AVPlayer后需单独调用AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)实现震动。 - 测试时需确认设备媒体音量未调至0——
playback类别仍遵循媒体音量设置。
内容的提问来源于stack exchange,提问作者Jan L
相关产品推荐
相关产品推荐

