You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在设备静音时通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 13:32:23