La biblioteca Core-Telecom
optimiza el proceso de integración de tu aplicación de llamadas con la plataforma de Android, ya que proporciona un conjunto de APIs sólido y coherente.
Si deseas explorar implementaciones prácticas, puedes encontrar aplicaciones de muestra en GitHub:
- App de ejemplo liviana: Es un ejemplo mínimo que demuestra el uso de la API de
Core-Telecom
. Ideal para comprender rápidamente los conceptos fundamentales. - Aplicación de ejemplo integral (desarrollada por el equipo de Core-Telecom): Es una aplicación con más funciones que muestra prácticas recomendadas y funciones avanzadas de telecomunicaciones. Este es un gran recurso para comprender situaciones de integración complejas.
Configura Core-Telecom
Agrega la dependencia androidx.core:core-telecom
al archivo build.gradle
de tu app:
dependencies {
implementation ("androidx.core:core-telecom:1.0.0")
}
Declara el permiso MANAGE_OWN_CALLS
en tu AndroidManifest.xml
:
<uses-permission android:name="android.permission.MANAGE_OWN_CALLS" />
Cómo registrar la aplicación
Registra tu app de llamadas con Android usando CallsManager
para comenzar a agregar llamadas al sistema. Cuando te registres, especifica las capacidades de tu app (por ejemplo, compatibilidad con audio y video):
val callsManager = CallsManager(context)
val capabilities: @CallsManager.Companion.Capability Int =
(CallsManager.CAPABILITY_BASELINE or
CallsManager.CAPABILITY_SUPPORTS_VIDEO_CALLING)
callsManager.registerAppWithTelecom(capabilities)
Administración de llamadas
Usa las APIs de Core-Telecom para crear y administrar un ciclo de vida de llamadas.
Cómo crear una llamada
El objeto CallAttributesCompat
define las propiedades de una llamada única,
que puede tener las siguientes características:
displayName
: Es el nombre del emisor.address
: Es la dirección de llamada (por ejemplo, número de teléfono o vínculo de reunión).direction
: Llamada entrante o saliente.callType
: Audio o video.callCapabilities
: Admite transferencia y retención.
Este es un ejemplo de cómo crear una llamada entrante:
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
)
}
Cómo agregar una llamada
Usa callsManager.addCall
con CallAttributesCompat
y devoluciones de llamada para agregar una llamada nueva al sistema y administrar las actualizaciones de la superficie remota. El callControlScope
dentro del bloque addCall
permite principalmente que tu app realice la transición del estado de la llamada y reciba actualizaciones de audio:
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.
}
Cómo responder una llamada
Responde una llamada entrante dentro de CallControlScope
:
when (val result = answer(CallAttributesCompat.CALL_TYPE_AUDIO_CALL)) {
is CallControlResult.Success -> { /* Call answered */ }
is CallControlResult.Error -> { /* Handle error */ }
}
Cómo rechazar una llamada
Rechaza una llamada con disconnect()
con DisconnectCause.REJECTED
dentro de CallControlScope
:
disconnect(DisconnectCause(DisconnectCause.REJECTED))
Cómo activar una llamada saliente
Cómo establecer una llamada saliente como activa una vez que la parte remota responde:
when (val result = setActive()) {
is CallControlResult.Success -> { /* Call active */ }
is CallControlResult.Error -> { /* Handle error */ }
}
Coloca una llamada en espera
Usa setInactive()
para poner una llamada en espera:
when (val result = setInactive()) {
is CallControlResult.Success -> { /* Call on hold */ }
is CallControlResult.Error -> { /* Handle error */ }
}
Cómo desconectar una llamada
Desconecta una llamada con disconnect()
con un DisconnectCause
:
disconnect(DisconnectCause(DisconnectCause.LOCAL))
Administra los extremos de audio de las llamadas
Observa y administra los extremos de audio con Flow
de currentCallEndpoint
, availableEndpoints
y isMuted
dentro de CallControlScope
fun observeAudioStateChanges(callControlScope: CallControlScope) {
with(callControlScope) {
launch { currentCallEndpoint.collect { /* Update UI */ } }
launch { availableEndpoints.collect { /* Update UI */ } }
launch { isMuted.collect { /* Handle mute state */ } }
}
}
Cambia el dispositivo de audio activo con requestEndpointChange()
:
coroutineScope.launch {
callControlScope.requestEndpointChange(callEndpoint)
}
Compatibilidad con primer plano
La biblioteca usa ConnectionService
(Android 13 nivel de API 33 y versiones anteriores) o foregroundtypes (Android 14 nivel de API 34 y versiones posteriores) para la compatibilidad en primer plano.
Como parte de los requisitos en primer plano, la aplicación debe publicar una notificación para que los usuarios sepan que se está ejecutando en primer plano.
Para asegurarte de que tu app obtenga prioridad de ejecución en primer plano, crea una notificación una vez que agregues la llamada con la plataforma. La prioridad en primer plano se quita cuando tu app finaliza la llamada o cuando tu notificación ya no es válida.
Obtén más información sobre los servicios en primer plano.
Compatibilidad remota con Surface
Los dispositivos remotos (relojes inteligentes, auriculares Bluetooth y Android Auto) pueden administrar llamadas sin interactuar directamente con el teléfono. Tu app debe implementar las lambdas de devolución de llamada (onAnswerCall
, onSetCallDisconnected
, onSetCallActive
, onSetCallInactive
) que se proporcionan a CallsManager.addCall
para controlar las acciones que inician estos dispositivos.
Cuando se produce una acción remota, se invoca la lambda correspondiente.
Completación correcta de los indicadores lambda que indican que se procesó el comando. Si no se puede obedecer el comando, la expresión lambda debe arrojar una excepción.
La implementación adecuada garantiza un control de llamadas sin problemas en diferentes dispositivos. Realiza pruebas exhaustivas con varias plataformas remotas.