La nuova libreria Android Telecom Jetpack consente di comunicare alla piattaforma stato in cui si trova la chiamata. Puoi trovare il codice sorgente e un'app di esempio su GitHub.
Dipendenze e autorizzazioni
Innanzitutto, apri il file build.gradle del modulo dell'app e aggiungi una dipendenza per il parametro Modulo telecomunicazioni androidx:
dependencies {
implementation ("androidx.core:core-telecom:1.0.0-alpha02")
}
Nel file manifest dell'app, dichiara che l'app utilizza MANAGE_OWN_CALLS
.
autorizzazione:
<uses-permission android:name="android.permission.MANAGE_OWN_CALLS" />
Registra l'applicazione
Per comunicare ad Android la tua app, devi registrarla e le sue funzionalità. Questa funzionalità indica ad Android le funzionalità supportate dalla tua app, come videochiamate, chiamate streaming e chiamate in attesa. Queste informazioni sono importanti per consentire ad Android di configurare per interagire con le funzionalità dell'app.
private val callsManager = CallsManager(context)
var capabilities: @CallsManager.Companion.Capability Int =
CallsManager.CAPABILITY_BASELINE or
CallsManager.CAPABILITY_SUPPORTS_CALL_STREAMING or
CallsManager.CAPABILITY_SUPPORTS_VIDEO_CALLING
callsManager.registerAppWithTelecom(capabilities)
Integrazione della piattaforma
I due scenari di chiamata più comuni per qualsiasi applicazione di chiamata sono in entrata e chiamate in uscita. Per registrare correttamente l'indirizzo della chiamata e avvisa l'utente in modo appropriato con notifiche, utilizza le API indicate di seguito.
Registrare una chiamata
Questo esempio mostra come registrare una chiamata in arrivo:
companion object {
const val APP_SCHEME = "MyCustomScheme"
const val ALL_CALL_CAPABILITIES = (CallAttributes.SUPPORTS_SET_INACTIVE
or CallAttributes.SUPPORTS_STREAM or CallAttributes.SUPPORTS_TRANSFER)
const val INCOMING_NAME = "Luke"
val INCOMING_URI: Uri = Uri.fromParts(APP_SCHEME, "", "")
// Define all possible properties for CallAttributes
val INCOMING_CALL_ATTRIBUTES =
CallAttributes(
INCOMING_NAME,
INCOMING_URI,
DIRECTION_INCOMING,
CALL_TYPE_VIDEO_CALL,
ALL_CALL_CAPABILITIES)
}
L'oggetto callAttributes
può avere le seguenti proprietà:
displayName
: nome del chiamante, riunione o sessione.address
: l'indirizzo della chiamata. Tieni presente che questa opzione può essere estesa a una riunione .direction
: la direzione della chiamata, ad esempio in arrivo o in uscita.callType
: informazioni relative ai dati trasmessi, ad esempio i video e audio.callCapabilities
: un oggetto che specifica le funzionalità della chiamata.
L'oggetto callCapabilities
può avere le seguenti proprietà:
streaming
: indica se la chiamata supporta lo streaming audio a un'altra persona Dispositivo con tecnologia Android.transfer
: indica se è possibile trasferire la chiamata.hold
: indica se la chiamata può essere messa in attesa.
Aggiungi una chiamata
Il metodo addCall()
restituisce un'eccezione se il dispositivo non supporta
telecom o se si è verificato un errore durante la configurazione della chiamata.
try {
callsManager.addCall(
INCOMING_CALL_ATTRIBUTES,
onIsCallAnswered, // Watch needs to know if it can answer the call
onIsCallDisconnected,
onIsCallActive,
onIsCallInactive
) {
callControlScope = this
}
}
Rispondere a una chiamata
Una volta effettuata una chiamata in arrivo, devi rispondere o rifiutare. Questo l'esame dimostra come rispondere a una chiamata:
when (answer(CallAttributesCompat.CALL_TYPE_AUDIO_CALL)) {
is CallControlResult.Success -> {
}
is CallControlResult.Error -> {
}
}
Se è in corso un'altra chiamata, answer()
tornerà
CallControlResult.Error
, che indica il motivo per cui non è stato possibile rispondere alla chiamata. Nella
in questo caso l'utente deve mettere in attesa l'altra chiamata.
Rifiutare una chiamata
Per rifiutare una chiamata, disconnettila con DisconnectCause.Rejected
.
fun onRejectCall(){
coroutineScope.launch {
callControlScope?.let {
it.disconnect(DisconnectCause(DisconnectCause.REJECTED))
}
}
}
Chiamata in uscita
Quando si effettua una chiamata in uscita, dopo che l'interlocutore remoto risponde, è necessario impostare il chiamata a active per comunicare alla piattaforma che la chiamata è in corso:
when (setActive()) {
is CallControlResult.Success -> {
onIsCallActive()
}
is CallControlResult.Error -> {
updateCurrentCall {
copy(errorCode = result.errorCode)
}
}
}
Mettere in attesa una chiamata
Se la tua app per le chiamate supporta le chiamate in attesa, usa setInActive
per indicare al
piattaforma su cui la chiamata non è attiva e che microfono e videocamera sono liberi
può essere usato da altre app:
when (setInActive()) {
is CallControlResult.Success -> {
}
is CallControlResult.Error -> {
updateCurrentCall {
copy(errorCode = result.errorCode)
}
}
}
Disconnetterti
Per disconnettere una chiamata, chiedi allo stack di Telecomunicazioni di disconnettersi fornendo un causa valida:
coroutineScope.launch {
callControlScope?.disconnect(DisconnectCause(DisconnectCause.LOCAL))
}
Indirizza l'audio
Durante una chiamata, a volte gli utenti passano da un dispositivo all'altro, ad esempio uno speaker,
auricolare o dispositivo Bluetooth. Utilizza availableEndpoints
e
currentCallEndpoint
API per ottenere un elenco di tutti i dispositivi disponibili
l'utente e il dispositivo attivo.
Questo esempio combina entrambi i flussi per creare un oggetto UI da mostrare all'utente elenco di dispositivi e quale è attivo:
availableEndpoint = combine(callControlScope.availableEndpoints,
callControlScope.currentCallEndpoint) {
availableDevices: List<CallEndpoint>, activeDevice : CallEndpoint ->
availableDevices.map {
EndPointUI(
isActive = activeDevice.endpointName == it.endpointName, it
)
}
}
Per cambiare un dispositivo attivo, usa requestEndpointChange
con
CallEndpoint
a cui vuoi passare.
coroutineScope.launch {
callControlScope?.requestEndpointChange(callEndpoint)
}
Supporto in primo piano
La libreria Telecom include il supporto in primo piano. Questa libreria utilizza
ConnectionService
per i dispositivi con Android 13 e versioni precedenti. Per Android 14 e
più in alto utilizza il microfono e la fotocamera in primo piano per
supportare i servizi in primo piano. Scopri di più sui servizi in primo piano.
Nell'ambito dei requisiti in primo piano, l'applicazione deve pubblicare una notifica affinché gli utenti sappiano che l'applicazione è in esecuzione in primo piano.
Per assicurarti che l'esecuzione in primo piano della tua app sia prioritaria, crea una una volta registrata la chiamata sulla piattaforma. Priorità in primo piano viene rimosso quando la tua app termina la chiamata o quando la notifica non è più valida.
is TelecomCall.Registered -> {
val notification = createNotification(call)
notificationManager.notify(TELECOM_NOTIFICATION_ID, notification)
}
Supporto di Surface
Gli smartwatch hanno un'applicazione generica di ricezione degli endpoint. Questa applicazione fornisce l'utente con un'interfaccia di base come rispondere, rifiutare e disconnettersi chiamate. L'applicazione supporta queste azioni implementando funzioni lambda che indicano alla piattaforma che hai eseguito l'azione sul dispositivo.
Ogni funzione lambda scade dopo 5 secondi con una transazione non riuscita se le tue l'applicazione non risponde.
callsManager.addCall(
attributes,
onIsCallAnswered, // Watch/Auto need to know if they can answer the call
onIsCallDisconnected,
onIsCallActive,
onIsCallInactive
) {
//Call Scope
}
/**
* Can the call be successfully answered??
* TIP: Check the connection/call state to see if you can answer a call
* Example you may need to wait for another call to hold.
**/
val onIsCallAnswered: suspend(type: Int) -> Unit = {}
/**
* Can the call perform a disconnect
*/
val onIsCallDisconnected: suspend (cause: DisconnectCause) -> Unit = {}
/**
* Check is see if you can make the call active.
* Other calls and state might stop us from activating the call
*/
val onIsCallActive: suspend () -> Unit = {
updateCurrentCall {
}
}
/**
* Check to see if you can make the call inactivate
*/
val onIsCallInactive: suspend () -> Unit = {}