非默认拨号器VoIP应用能否暂停原生GSM通话?Android技术咨询
问题解答
最新Android版本支持情况
最新Android 13/14版本完全支持该功能,第三方VoIP应用无需设置为默认拨号器,即可实现接听VoIP来电时暂停原生GSM通话的效果——核心是利用Android官方提供的通话框架集成API,而非单纯依赖音频焦点控制。
可行实现方案
1. 核心方案:使用ConnectionService
这是Android为第三方VoIP应用提供的标准集成API,能让你的应用接入系统通话管理框架,自动触发通话切换逻辑(类似WhatsApp的行为),无需系统级权限。
关键步骤:
- 声明权限:在
AndroidManifest.xml中添加必要权限:
<uses-permission android:name="android.permission.CALL_PHONE" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <!-- 若使用SIP协议,需额外添加 --> <uses-permission android:name="android.permission.USE_SIP" />
- 注册ConnectionService:在Manifest中注册自定义的
ConnectionService实现:
<service android:name=".MyVoipConnectionService" android:permission="android.permission.BIND_CONNECTION_SERVICE"> <intent-filter> <action android:name="android.telecom.ConnectionService" /> </intent-filter> </service>
- 实现通话逻辑:
- 创建自定义
Connection子类,处理VoIP通话的接通、保持等状态。 - 当VoIP来电被用户接听时,调用
setActive(true),系统会自动将正在进行的原生GSM通话切换为保持状态;当VoIP通话结束时,系统会恢复原生GSM通话。
- 创建自定义
2. 音频焦点问题的修正
你之前单独请求音频焦点得到AUDIOFOCUS_REQUEST_DELAYED,原因是原生GSM通话的音频焦点优先级为AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE(最高级别),单独请求无法直接抢占。结合ConnectionService后,系统会自动处理音频焦点的切换,无需手动请求。如果需要手动处理,需调整请求参数:
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); // 设置通话类音频属性,让系统识别为高优先级通话 AudioAttributes audioAttributes = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION) .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH) .build(); AudioFocusRequest focusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE) .setAudioAttributes(audioAttributes) .setAcceptsDelayedFocusGain(true) .setOnAudioFocusChangeListener(new AudioManager.OnAudioFocusChangeListener() { @Override public void onAudioFocusChange(int focusChange) { if (focusChange == AudioManager.AUDIOFOCUS_GAIN) { // 音频焦点已获取,启动VoIP通话音频 } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) { // 音频焦点丢失,暂停VoIP通话音频 } } }) .build(); int result = audioManager.requestAudioFocus(focusRequest); if (result == AudioManager.AUDIOFOCUS_REQUEST_DELAYED) { // 等待焦点回调,不要立即处理音频 }
注意事项
InCallService确实是系统拨号器专属API,第三方应用无法获取系统级权限来使用,因此不适合你的场景。- 确保VoIP通话在前台服务中运行,避免被系统后台杀死,影响通话切换逻辑。
内容的提问来源于stack exchange,提问作者Yehuda Goldshtein
相关产品推荐
相关产品推荐

