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

如何在通话应用中播放默认呼叫等待音?

实现通话等待接通时的默认提示音播放

嘿,这个需求在通话类应用里太普遍了,我来分享几个不同平台的实现思路和代码示例,你可以根据自己的开发平台来选:

Android 平台实现

Android上推荐用SoundPool来播放短循环音效(默认等待提示音大多是短音频循环),它的资源占用更低,响应更快:

// 初始化SoundPool
private val soundPool = SoundPool.Builder()
    .setMaxStreams(1) // 只需要一个音频流
    .build()

// 加载提示音资源(比如放在res/raw/waiting_tone.mp3)
private var soundId: Int = 0
private var streamId: Int = 0

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // 加载音频
    soundId = soundPool.load(this, R.raw.waiting_tone, 1)
    // 监听加载完成
    soundPool.setOnLoadCompleteListener { _, _, _ ->
        // 可以在这里做预加载完成后的操作
    }
}

// 开始呼叫时播放提示音
fun startWaitingTone() {
    if (soundId != 0) {
        streamId = soundPool.play(
            soundId,
            1.0f, // 左音量
            1.0f, // 右音量
            1, // 优先级
            -1, // 循环次数:-1表示无限循环
            1.0f // 播放速率
        )
    }
}

// 通话接通时停止播放
fun stopWaitingTone() {
    if (streamId != 0) {
        soundPool.stop(streamId)
    }
}

// 记得在页面销毁时释放资源
override fun onDestroy() {
    super.onDestroy()
    soundPool.release()
}

另外要注意音频焦点的申请,避免和其他应用的音频冲突:

private val audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
private val audioFocusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT)
    .setOnAudioFocusChangeListener { focusChange ->
        // 处理焦点丢失的情况,比如暂停播放
        if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
            stopWaitingTone()
        }
    }
    .build()

// 播放前申请焦点
fun requestAudioFocus() {
    val result = audioManager.requestAudioFocus(audioFocusRequest)
    if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
        startWaitingTone()
    }
}

iOS 平台实现

iOS上用AVAudioPlayer就能轻松实现循环播放,记得处理权限和后台播放(如果需要的话):

import AVFoundation

class CallManager: NSObject, AVAudioPlayerDelegate {
    private var waitingPlayer: AVAudioPlayer?

    func startWaitingTone() {
        guard let url = Bundle.main.url(forResource: "waiting_tone", withExtension: "mp3") else {
            print("提示音资源不存在")
            return
        }
        do {
            // 初始化播放器
            waitingPlayer = try AVAudioPlayer(contentsOf: url)
            waitingPlayer?.numberOfLoops = -1 // 无限循环
            waitingPlayer?.delegate = self
            waitingPlayer?.play()
        } catch {
            print("播放器初始化失败:\(error)")
        }
    }

    func stopWaitingTone() {
        waitingPlayer?.stop()
        waitingPlayer = nil
    }

    // 播放器出错时的处理
    func audioPlayerDecodeErrorDidOccur(_ player: AVAudioPlayer, error: Error?) {
        print("播放出错:\(error?.localizedDescription ?? "未知错误")")
        stopWaitingTone()
    }
}

如果需要在后台播放,要在Info.plist中添加UIBackgroundModes,包含audio项。

Flutter 跨平台实现

用第三方插件audioplayers(热门音频插件),实现起来更简单:

首先在pubspec.yaml中添加依赖:

dependencies:
  audioplayers: ^5.2.0

然后实现播放逻辑:

import 'package:audioplayers/audioplayers.dart';

class CallService {
  final AudioPlayer _audioPlayer = AudioPlayer();
  bool _isPlaying = false;

  Future<void> startWaitingTone() async {
    if (!_isPlaying) {
      // 加载本地资源(放在assets/audio/waiting_tone.mp3,记得在pubspec.yaml中声明assets)
      await _audioPlayer.play(AssetSource('audio/waiting_tone.mp3'));
      await _audioPlayer.setReleaseMode(ReleaseMode.loop); // 设置循环播放
      _isPlaying = true;
    }
  }

  Future<void> stopWaitingTone() async {
    if (_isPlaying) {
      await _audioPlayer.stop();
      _isPlaying = false;
    }
  }
}

关键注意点

  • 及时停止播放:一定要在通话接通的回调里调用停止方法,避免和通话音频重叠。
  • 资源格式:尽量用MP3、AAC这类兼容性好的音频格式,确保不同设备都能正常播放。
  • 静音处理:如果用户手机处于静音模式,要考虑是否播放提示音,或者遵循系统的音频策略。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:42:23