Core-Telecom

La libreria Core-Telecom semplifica il processo di integrazione della tua applicazione di chiamata con la piattaforma Android fornendo un insieme solido e coerente di API

Se vuoi esplorare le implementazioni pratiche, puoi trovare applicazioni di esempio su GitHub:

Configurare Core-Telecom

Aggiungi la dipendenza androidx.core:core-telecom al file build.gradle dell'app:

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

Dichiara l'autorizzazione MANAGE_OWN_CALLS in AndroidManifest.xml:

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

Registrazione dell'our app

Registra la tua app di chiamata con Android utilizzando CallsManager per iniziare ad aggiungere chiamate al sistema. Al momento della registrazione, specifica le funzionalità della tua app (ad esempio, supporto audio e video):

val callsManager = CallsManager(context)

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

callsManager.registerAppWithTelecom(capabilities)

Gestione chiamate

Utilizza le API Core-Telecom per creare e gestire il ciclo di vita di una chiamata.

Creare una chiamata

L'oggetto CallAttributesCompat definisce le proprietà di una chiamata univoca, che può avere le seguenti caratteristiche:

  • displayName: nome del chiamante.
  • address: indirizzo di chiamata (ad esempio numero di telefono, link alla riunione).
  • direction: in entrata o in uscita.
  • callType: audio o video.
  • callCapabilities: supporta il trasferimento e la messa in attesa.

Di seguito è riportato un esempio di come creare una chiamata in arrivo:

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
    )
}

Aggiungi una chiamata

Utilizza callsManager.addCall con CallAttributesCompat e i callback per aggiungere una nuova chiamata al sistema e gestire gli aggiornamenti delle piattaforme da remoto. Il codice callControlScope all'interno del blocco addCall consente principalmente all'app di gestire la transizione dello stato della chiamata e di ricevere aggiornamenti 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.
}

Rispondere a una chiamata

Rispondi a una chiamata in arrivo entro CallControlScope:

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

Rifiutare una chiamata

Rifiutare una chiamata utilizzando disconnect() con DisconnectCause.REJECTED all'interno di CallControlScope:

disconnect(DisconnectCause(DisconnectCause.REJECTED))

Attivare una chiamata in uscita

Imposta una chiamata in uscita come attiva quando la parte remota risponde:

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

Mettere in attesa una chiamata

Usa setInactive() per mettere una chiamata in attesa:

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

Disconnettere una chiamata

Per disconnettere una chiamata utilizzando disconnect() con un DisconnectCause:

disconnect(DisconnectCause(DisconnectCause.LOCAL))

Gestire gli endpoint audio delle chiamate

Osserva e gestisci gli endpoint audio utilizzando i Flow currentCallEndpoint, availableEndpoints e isMuted all'interno del CallControlScope

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

Cambia il dispositivo audio attivo utilizzando requestEndpointChange():

coroutineScope.launch {
     callControlScope.requestEndpointChange(callEndpoint)
}

Supporto in primo piano

La libreria utilizza ConnectionService (Android 13, livello API 33 e versioni precedenti) o foregroundtypes (Android 14, livello API 34 e versioni successive) per il supporto in primo piano.

Nell'ambito dei requisiti per l'esecuzione in primo piano, l'applicazione deve pubblicare una notifica per informare gli utenti che è in esecuzione in primo piano.

Per assicurarti che la tua app abbia la priorità di esecuzione in primo piano, crea una notification dopo aver aggiunto la chiamata con la piattaforma. La priorità in primo piano viene rimossa quando l'app termina la chiamata o la notifica non è più valida.

Scopri di più sui servizi in primo piano.

Assistenza remota per Surface

I dispositivi remoti (smartwatch, cuffie Bluetooth, Android Auto) sono in grado di gestire le chiamate senza interazione diretta con lo smartphone. L'app deve implementare callback lambda (onAnswerCall, onSetCallDisconnected, onSetCallActive, onSetCallInactive) forniti a CallsManager.addCall per gestire le azioni avviate da questi dispositivi.

Quando si verifica un'azione remota, viene invocato il lambda corrispondente.

Completamento riuscito degli indicatori lambda che indicano che il comando è stato elaborato. Se il comando non può essere eseguito, la funzione lambda deve generare un'eccezione.

L'implementazione corretta garantisce un controllo senza interruzioni delle chiamate su diversi dispositivi. Esegui test approfonditi con varie piattaforme remote.