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

如何将VoIP通话功能集成至WearOS手表应用?

在WearOS中集成VoIP通话至原生通话模块

核心依赖与权限配置

  • 先在模块的build.gradle中引入WearOS核心依赖:
    implementation "com.google.android.wearable:wearable:2.9.0"
    
  • 在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.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    

用CallStyle构建系统识别的通话通知

要让WearOS原生通话模块接管,必须生成符合系统规范的通话通知,核心是使用CallStyle标记为VoIP通话:

private fun showIncomingCallNotification(callerName: String, callerNumber: String) {
    val callStyle = CallStyle.forIncomingCall(
        applicationContext,
        callerName,
        arrayOf(callerNumber),
        Uri.parse("tel:$callerNumber"),
        CallStyle.DEFAULT_CALL_TYPE_VOIP
    )

    val fullScreenIntent = PendingIntent.getActivity(
        applicationContext,
        0,
        Intent(applicationContext, CallActivity::class.java),
        PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
    )

    val notification = NotificationCompat.Builder(applicationContext, "VOIP_CALL_CHANNEL")
        .setSmallIcon(R.drawable.ic_phone_incoming)
        .setContentTitle("VoIP来电")
        .setContentText("$callerName ($callerNumber)")
        .setPriority(NotificationCompat.PRIORITY_HIGH)
        .setCategory(NotificationCompat.CATEGORY_CALL)
        .setStyle(callStyle)
        .setFullScreenIntent(fullScreenIntent, true)
        .build()

    NotificationManagerCompat.from(applicationContext).notify(1001, notification)
}

这里的CATEGORY_CALL和DEFAULT_CALL_TYPE_VOIP是关键,系统会据此将通知识别为原生通话流程的一部分。

实现InCallService绑定系统通话服务

通过继承InCallService,让应用的通话状态与系统原生通话模块同步:

class VoipInCallService : InCallService() {
    private val voipEngine = YourVoipEngine.getInstance()

    override fun onCallAdded(call: Call) {
        super.onCallAdded(call)
        // 监听通话状态变化,同步到自定义VoIP引擎
        call.registerCallback(object : Call.Callback() {
            override fun onStateChanged(call: Call, state: Int) {
                when (state) {
                    Call.STATE_ACTIVE -> voipEngine.acceptCurrentCall()
                    Call.STATE_DISCONNECTED -> voipEngine.endCurrentCall()
                }
            }
        })
    }

    override fun onCallRemoved(call: Call) {
        super.onCallRemoved(call)
        // 释放通话相关资源
        voipEngine.releaseCallResources()
    }
}

然后在AndroidManifest.xml中注册该服务:

<service
    android:name=".VoipInCallService"
    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>

手机与手表的通话状态同步

如果VoIP通话发起于手机端,需要通过Wearable Data Layer同步状态到手表:

手机端发送状态

fun syncCallStateToWatch(callState: String, callerName: String, callerNumber: String) {
    val dataMap = DataMap().apply {
        putString("call_state", callState)
        putString("caller_name", callerName)
        putString("caller_number", callerNumber)
    }
    val request = PutDataMapRequest.create("/voip_call_state").apply {
        dataMap.putAll(dataMap)
        setUrgent()
    }
    Wearable.getDataClient(applicationContext).putDataItem(request.asPutDataRequest())
}

手表端监听状态并触发通知

class CallDataListener : DataClient.OnDataChangedListener {
    override fun onDataChanged(dataEvents: DataEventBuffer) {
        dataEvents.forEach { event ->
            if (event.type == DataEvent.TYPE_CHANGED && event.dataItem.uri.path == "/voip_call_state") {
                val dataMap = DataMapItem.fromDataItem(event.dataItem).dataMap
                if (dataMap.getString("call_state") == "INCOMING") {
                    showIncomingCallNotification(
                        dataMap.getString("caller_name") ?: "未知联系人",
                        dataMap.getString("caller_number") ?: ""
                    )
                }
            }
        }
    }
}

记得在手表端的Activity或Service中注册这个监听器:

Wearable.getDataClient(this).addListener(callDataListener)

处理通话操作反馈

当用户在手表原生通话界面执行接听/挂断操作时,InCallService会收到状态回调,此时只需将操作同步到你的VoIP引擎即可完成闭环。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 07:27:33