如何在通话应用中播放默认呼叫等待音?
实现通话等待接通时的默认提示音播放
嘿,这个需求在通话类应用里太普遍了,我来分享几个不同平台的实现思路和代码示例,你可以根据自己的开发平台来选:
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
相关产品推荐
相关产品推荐

