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

如何实现可替代系统默认的Android自定义拨号器(含通话转移与会议)

Android自定义拨号器:通话转移与会议功能实现方案

针对你已经实现基础通话功能的自定义默认拨号器,下面是添加通话转移和会议功能的具体落地步骤,都是适合新手的操作方法:

一、通话转移功能实现

1. 搞定必要权限

通话转移需要危险权限,先在AndroidManifest.xml里声明:

<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- 部分国产机型可能需额外添加 -->
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />

然后在Activity里添加运行时权限请求(Android 6.0+必须做):

private val REQUEST_PERM_CODE = 1001
private val requiredPermissions = arrayOf(
    Manifest.permission.CALL_PHONE,
    Manifest.permission.READ_PHONE_STATE
)

fun checkCallPermissions() {
    val missingPerms = requiredPermissions.filter {
        ContextCompat.checkSelfPermission(this, it) != PackageManager.PERMISSION_GRANTED
    }
    if (missingPerms.isNotEmpty()) {
        ActivityCompat.requestPermissions(this, missingPerms.toTypedArray(), REQUEST_PERM_CODE)
    }
}

记得在onRequestPermissionsResult里处理权限申请结果,确保权限通过后再调用功能。

2. 实现转移逻辑

(1)快速实现(新手首选)

不想处理复杂的版本兼容,直接调用系统通话转移设置界面让用户自行配置:

fun openSystemCallForwardSettings() {
    val intent = Intent(Intent.ACTION_CALL_FORWARDING)
    startActivity(intent)
}

这个方法简单可靠,无需考虑版本差异。

(2)API 28+原生实现(自定义界面用)

Android 9.0(API 28)之后提供了直接操作通话转移的API,适合做自定义设置界面:

// 查询当前转移设置
fun queryCallForwardSettings() {
    val telecomManager = getSystemService(TelecomManager::class.java)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
        telecomManager.getCallForwardingSettings(object : TelecomManager.CallForwardingCallback() {
            override fun onCallForwardingSettingsLoaded(settings: MutableList<CallForwardingSettings>?) {
                settings?.forEach {
                    Log.d("CallForward", "类型: ${it.type}, 号码: ${it.number}, 已开启: ${it.isEnabled}")
                }
            }
        })
    }
}

// 设置无条件通话转移
fun setUnconditionalForward(number: String) {
    val telecomManager = getSystemService(TelecomManager::class.java)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
        val forwardSettings = CallForwardingSettings.Builder()
            .setType(CallForwardingSettings.TYPE_UNCONDITIONAL) // 无条件转移
            .setNumber(number)
            .setEnabled(true)
            .build()
        telecomManager.setCallForwarding(forwardSettings, object : TelecomManager.ActionCallback() {
            override fun onSuccess() {
                // 转移设置成功,提示用户
            }

            override fun onFailure(errorCode: Int) {
                // 处理失败,比如权限不足、号码无效
            }
        })
    }
}

常见转移类型:TYPE_UNCONDITIONAL(无条件)、TYPE_BUSY(占线时)、TYPE_NO_ANSWER(无人接听时)。

二、会议通话功能实现

会议通话依赖InCallService(你的基础应用应该已实现该服务),核心是合并多个通话。

1. 确认InCallService注册正确

检查AndroidManifest.xml里的服务注册,确保没写错:

<service android:name=".MyInCallService"
    android:permission="android.permission.BIND_INCALL_SERVICE">
    <meta-data android:name="android.telecom.IN_CALL_SERVICE_UI" android:value="true" />
    <intent-filter>
        <action android:name="android.telecom.InCallService" />
    </intent-filter>
</service>

2. 在InCallService里跟踪通话列表

重写onCallAdded和onCallRemoved方法,记录当前所有通话:

class MyInCallService : InCallService() {
    private val activeCalls = mutableListOf<Call>()

    override fun onCallAdded(call: Call) {
        super.onCallAdded(call)
        activeCalls.add(call)
        // 通知UI更新,比如有2个及以上通话时显示合并按钮
        notifyUiUpdateMergeButton()
    }

    override fun onCallRemoved(call: Call) {
        super.onCallRemoved(call)
        activeCalls.remove(call)
        notifyUiUpdateMergeButton()
    }

    // 用广播或ViewModel通知UI层更新按钮状态
    private fun notifyUiUpdateMergeButton() {
        val hasMultipleCalls = activeCalls.size >= 2
        // 示例:发送广播告知Activity显示/隐藏合并按钮
    }
}

3. 实现合并通话为会议

用户点击合并按钮时,调用Call.merge()方法,需确保一个通话活跃、一个通话保持:

fun mergeCallsIntoConference() {
    val activeCall = activeCalls.find { it.state == Call.STATE_ACTIVE }
    val heldCall = activeCalls.find { it.state == Call.STATE_HOLDING }
    if (activeCall != null && heldCall != null) {
        activeCall.merge(heldCall)
    }
}

4. 会议通话的其他操作

  • 添加新通话到会议:先拨打新电话,接通后重复合并操作
  • 拆分会议:找到状态为Call.STATE_CONFERENCE的通话,调用call.split()即可拆分为单个通话

三、新手必看注意事项

  • 必须用真实Android设备测试,模拟器基本不支持完整的通话/会议功能
  • 确保你的应用是默认电话应用,否则TelecomManager和InCallService的大部分API会失效
  • 低版本Android(API<28)建议用系统Intent跳转设置的方式实现通话转移,避免兼容问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 03:44:51