Core-Telecom

Core-Telecom 库通过提供一组强大且一致的 API,简化了将调用应用与 Android 平台集成的过程

如果您想探索实际实现,可以前往 GitHub 查找示例应用:

设置 Core-Telecom

androidx.core:core-telecom 依赖项添加到应用的 build.gradle 文件中:

dependencies {
    implementation ("androidx.core:core-telecom:1.0.0")
}

AndroidManifest.xml 中声明 MANAGE_OWN_CALLS 权限:

<uses-permission android:name="android.permission.MANAGE_OWN_CALLS" />

注册您的应用程序

使用 CallsManager 向 Android 注册调用应用,以开始向系统添加调用。注册时,请指定应用的功能(例如音频、视频支持):

val callsManager = CallsManager(context)

val capabilities: @CallsManager.Companion.Capability Int =
    (CallsManager.CAPABILITY_BASELINE or
          CallsManager.CAPABILITY_SUPPORTS_VIDEO_CALLING)

callsManager.registerAppWithTelecom(capabilities)

通话管理

使用 Core-Telecom API 创建和管理通话生命周期。

创建通话

CallAttributesCompat 对象定义了唯一调用的属性,该调用可以具有以下特性:

  • displayName:调用方名称。
  • address:通话地址(例如电话号码、会议链接)。
  • direction:传入或传出。
  • callType:音频或视频。
  • callCapabilities:支持转接和保持通话。

以下示例展示了如何创建来电:

fun createIncomingCallAttributes(
    callerName: String,
    callerNumber: String,
    isVideoCall: Boolean): CallAttributesCompat {
    val addressUri = Uri.parse("YourAppScheme:$callerNumber")

    // Define capabilities supported by your call.
    val callCapabilities = CallAttributesCompat.CallCapability(
        supportsSetInactive = CallAttributesCompat.SUPPORTS_SET_INACTIVE // Call can be made inactive (implies hold)
    )

    return CallAttributesCompat(
        displayName = callerName,
        address = addressUri,
        direction = CallAttributesCompat.DIRECTION_INCOMING,
        callType = if (isVideoCall) CallAttributesCompat.CALL_TYPE_VIDEO_CALL else CallAttributesCompat.CALL_TYPE_AUDIO_CALL,
        callCapabilitiesCompat = callCapabilities
    )
}

添加通话

callsManager.addCallCallAttributesCompat 和回调结合使用,可向系统添加新调用并管理远程 Surface 更新。addCall 块中的 callControlScope 主要用于让应用转换通话状态并接收音频更新:

try {
    callsManager.addCall(
        INCOMING_CALL_ATTRIBUTES,
        onAnswerCall, // Watch needs to know if it can answer the call.
        onSetCallDisconnected,
        onSetCallActive,
        onSetCallInactive
    ) {
        // The call was successfully added once this scope runs.
        callControlScope = this
    }
}
catch(addCallException: Exception){
   // Handle the addCall failure.
}

接听来电

CallControlScope 中接听来电:

when (val result = answer(CallAttributesCompat.CALL_TYPE_AUDIO_CALL)) {
    is CallControlResult.Success -> { /* Call answered */ }
    is CallControlResult.Error -> { /* Handle error */ }
}

拒绝来电

CallControlScope 中使用 DisconnectCause.REJECTEDdisconnect() 拒接来电:

disconnect(DisconnectCause(DisconnectCause.REJECTED))

将外拨电话设为活跃状态

在远程方接听后,将外拨通话设为“正在通话”状态:

when (val result = setActive()) {
    is CallControlResult.Success -> { /* Call active */ }
    is CallControlResult.Error -> { /* Handle error */ }
}

将通话置于保持状态

使用 setInactive() 将通话置于保持状态:

when (val result = setInactive()) {
    is CallControlResult.Success -> { /* Call on hold */ }
    is CallControlResult.Error -> { /* Handle error */ }
}

断开通话

使用 disconnect()DisconnectCause 断开通话:

disconnect(DisconnectCause(DisconnectCause.LOCAL))

管理通话音频端点

使用 CallControlScope 中的 currentCallEndpointavailableEndpointsisMuted Flow 监控和管理音频端点

fun observeAudioStateChanges(callControlScope: CallControlScope) {
    with(callControlScope) {
        launch { currentCallEndpoint.collect { /* Update UI */ } }
        launch { availableEndpoints.collect { /* Update UI */ } }
        launch { isMuted.collect { /* Handle mute state */ } }
    }
}

使用 requestEndpointChange() 更改活动音频设备:

coroutineScope.launch {
     callControlScope.requestEndpointChange(callEndpoint)
}

前台支持

该库使用 ConnectionService(Android 13 API 级别 33 及更低版本)或 foregroundtypes(Android 14 API 级别 34 及更高版本)来提供前台支持。

根据前台运行要求,应用必须发布通知,以便用户知道应用正在前台运行。

为确保您的应用获得前台执行优先级,请在添加与平台的调用后创建通知。当您的应用终止调用或通知不再有效时,系统会移除前台优先级。

详细了解前台服务

远程 Surface 支持

远程设备(智能手表、蓝牙耳机、Android Auto)无需直接与手机互动,即可管理通话。您的应用必须实现提供给 CallsManager.addCall 的回调 lambda(onAnswerCallonSetCallDisconnectedonSetCallActiveonSetCallInactive),以处理这些设备发起的操作。

当发生远程操作时,系统会调用相应的 lambda。

成功完成 lambda 会指示系统已处理该命令。如果无法执行该命令,lambda 应抛出异常。

正确的实现可确保在不同设备上无缝控制通话。使用各种远程 Surface 进行全面测试。