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

Swift中如何停止系统默认来电铃声并播放自定义铃声?

来电时播放自定义铃声但系统默认铃声仍在后台播放,如何停止?

我在来电时使用AVPlayer播放自定义铃声,但后台仍会播放系统默认铃声,请问如何停止系统的默认铃声?

相关代码

自定义铃声播放代码

var player: AVPlayer?

func playSound() {
    let url = Bundle.main.url(forResource: "Hold Music", withExtension: "mp3")!
    
    do {
        
        let audioSession = AVAudioSession.sharedInstance()

        try audioSession.setActive(false, options: [])

        try audioSession.setCategory(.playback,mode: .default, options: .mixWithOthers)
        try audioSession.setActive(true)
        
        let playerItem:AVPlayerItem = AVPlayerItem(url: url)
                player = AVPlayer(playerItem: playerItem)
        player?.volume = 1
        player?.play()
        
    } catch let error {
        print("lool \(error.localizedDescription)")
    }
}

通话状态监听代码

extension LandingViewController: CXCallObserverDelegate{
    
    func callObserver(_ callObserver: CXCallObserver, callChanged call: CXCall) {

        if call.hasEnded == true {
           player?.pause()
                   print("call Disconnected")

               }
               if call.isOutgoing == true && call.hasConnected == false {
                   print("call Dialing")
                   player?.pause()
               }
               if call.isOutgoing == false && call.hasConnected == false && call.hasEnded == false {
                   print("call Incoming")
                       self.playSound()
                   }
               if call.hasConnected == true && call.hasEnded == false {
                   print("call Connected")
                  player?.pause()
                 
               }
      }
        
}

问题原因

你当前的音频会话配置使用了.mixWithOthers选项,这会允许系统默认铃声与自定义铃声同时播放,无法中断系统铃声;同时代码中存在语法错误,也会影响功能正常执行。

解决方案

1. 修改音频会话配置,抢占音频焦点

移除.mixWithOthers选项,调整音频会话激活逻辑,确保自定义铃声播放时能中断系统铃声:

var player: AVPlayer?

func playSound() {
    guard let url = Bundle.main.url(forResource: "Hold Music", withExtension: "mp3") else {
        print("无法找到目标音频文件")
        return
    }
    
    do {
        let audioSession = AVAudioSession.sharedInstance()
        // 先停用当前会话,避免冲突
        try audioSession.setActive(false, options: .notifyOthersOnDeactivation)
        
        // 设置音频会话为播放类别,不允许混音,确保抢占音频焦点
        try audioSession.setCategory(.playback, mode: .default)
        // 激活会话,强制中断语音类音频(如系统来电铃声)
        try audioSession.setActive(true, options: .interruptSpokenAudioAndMixWithOthers)
        
        let playerItem = AVPlayerItem(url: url)
        player = AVPlayer(playerItem: playerItem)
        player?.volume = 1
        player?.play()
        
    } catch let error {
        print("音频播放错误:\(error.localizedDescription)")
    }
}

2. 修正通话状态监听代码的语法错误

原代码存在多余的闭合括号,修正后如下:

extension LandingViewController: CXCallObserverDelegate {
    func callObserver(_ callObserver: CXCallObserver, callChanged call: CXCall) {
        if call.hasEnded == true {
            player?.pause()
            print("call Disconnected")
        }
        if call.isOutgoing == true && call.hasConnected == false {
            print("call Dialing")
            player?.pause()
        }
        if call.isOutgoing == false && call.hasConnected == false && call.hasEnded == false {
            print("call Incoming")
            self.playSound()
        }
        if call.hasConnected == true && call.hasEnded == false {
            print("call Connected")
            player?.pause()
        }
    }
}

3. 额外优化:监听音频会话中断

添加音频会话中断通知,确保系统音频抢占时自动暂停自定义铃声:

// 在ViewController的viewDidLoad方法中添加监听
override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(self, selector: #selector(handleAudioSessionInterruption(_:)), name: AVAudioSession.interruptionNotification, object: AVAudioSession.sharedInstance())
}

// 处理音频中断的方法
@objc func handleAudioSessionInterruption(_ notification: Notification) {
    guard let info = notification.userInfo,
          let typeValue = info[AVAudioSessionInterruptionTypeKey] as? UInt,
          let type = AVAudioSession.InterruptionType(rawValue: typeValue) else {
        return
    }
    
    if type == .began {
        // 音频会话被中断,暂停自定义铃声
        player?.pause()
    }
}

内容的提问来源于stack exchange,提问作者Sourav Chakraborty

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 13:40:33