La nouvelle bibliothèque Android Telecom Jetpack permet d'indiquer facilement à la plate-forme dans lequel se trouve votre appel. Vous trouverez le code source et un exemple d'application sur GitHub
Dépendances et autorisations
Commencez par ouvrir le fichier build.gradle du module d'application et ajoutez une dépendance pour le Module androidx Telecom:
dependencies {
implementation ("androidx.core:core-telecom:1.0.0-alpha02")
}
Dans le fichier manifeste de votre application, déclarez qu'elle utilise le paramètre MANAGE_OWN_CALLS
.
autorisation:
<uses-permission android:name="android.permission.MANAGE_OWN_CALLS" />
Enregistrer l'application
Pour faire connaître votre application à Android, vous devez l'enregistrer ainsi que ses fonctionnalités. Cela indique à Android les fonctionnalités compatibles avec votre appli, comme les appels vidéo, le streaming et la mise en attente des appels. Ces informations sont importantes pour qu'Android puisse configurer pour fonctionner avec les fonctionnalités de votre application.
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)
Intégration à la plate-forme
Les deux scénarios d'appel les plus courants pour toute application appelante sont et les appels sortants. Pour enregistrer correctement la direction de l'appel et notifier correctement l'utilisateur à l'aide de notifications, utilisez les API ci-dessous.
Enregistrer un appel
Cet exemple montre comment enregistrer un appel entrant:
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'objet callAttributes
peut avoir les propriétés suivantes:
displayName
: nom de l'appelant, de la réunion ou de la session.address
: adresse de l'appel. Notez que cela peut être étendu à une réunion .direction
: sens de l'appel (entrant ou sortant, par exemple).callType
: informations liées aux données transmises, telles que les vidéos et audio.callCapabilities
: objet qui spécifie les capacités de l'appel.
L'objet callCapabilities
peut avoir les propriétés suivantes:
streaming
: indique si l'appel permet de diffuser du contenu audio vers un autre Appareil Androidtransfer
: indique si l'appel peut être transféré.hold
: indique si l'appel peut être mis en attente.
Ajouter un appel
La méthode addCall()
renvoie une exception si l'appareil n'est pas compatible
télécommunications, ou si une erreur s'est produite lors de la configuration de l'appel.
try {
callsManager.addCall(
INCOMING_CALL_ATTRIBUTES,
onIsCallAnswered, // Watch needs to know if it can answer the call
onIsCallDisconnected,
onIsCallActive,
onIsCallInactive
) {
callControlScope = this
}
}
Répondre à un appel
Une fois que vous avez passé un appel entrant, vous devez y répondre ou le refuser. Ce montre comment répondre à un appel:
when (answer(CallAttributesCompat.CALL_TYPE_AUDIO_CALL)) {
is CallControlResult.Success -> {
}
is CallControlResult.Error -> {
}
}
Si un autre appel est en cours, answer()
renvoie
CallControlResult.Error
, qui indique pourquoi l'appel n'a pas pu être pris. Dans
dans ce cas, l'utilisateur doit mettre l'autre appel en attente.
Refuser un appel
Pour refuser un appel, mettez fin à l'appel avec DisconnectCause.Rejected
.
fun onRejectCall(){
coroutineScope.launch {
callControlScope?.let {
it.disconnect(DisconnectCause(DisconnectCause.REJECTED))
}
}
}
Appel sortant
Lorsque vous passez un appel sortant, une fois que l'interlocuteur a répondu, vous devez définir le paramètre Appelez la méthode active pour indiquer à la plate-forme que l'appel est en cours:
when (setActive()) {
is CallControlResult.Success -> {
onIsCallActive()
}
is CallControlResult.Error -> {
updateCurrentCall {
copy(errorCode = result.errorCode)
}
}
}
Mettre un appel en attente
Si votre application d'appel prend en charge la mise en attente des appels, utilisez setInActive
pour indiquer à la
plate-forme sur laquelle votre appel n'est pas actif et sur lequel le micro et la caméra sont libres
être utilisées par d'autres applications:
when (setInActive()) {
is CallControlResult.Success -> {
}
is CallControlResult.Error -> {
updateCurrentCall {
copy(errorCode = result.errorCode)
}
}
}
Déconnecter
Pour mettre fin à un appel, demandez à la pile Telecom de se déconnecter en fournissant un cause valide:
coroutineScope.launch {
callControlScope?.disconnect(DisconnectCause(DisconnectCause.LOCAL))
}
Rediriger l'audio
Lors d'un appel, les utilisateurs passent parfois d'un appareil à un autre, comme une enceinte,
ou un appareil Bluetooth. Utiliser availableEndpoints
et
currentCallEndpoint
pour obtenir la liste de tous les appareils disponibles
et l'appareil actif.
Cet exemple combine les deux procédures pour créer un objet UI qui présente à l'utilisateur liste des appareils et de ceux qui sont actifs:
availableEndpoint = combine(callControlScope.availableEndpoints,
callControlScope.currentCallEndpoint) {
availableDevices: List<CallEndpoint>, activeDevice : CallEndpoint ->
availableDevices.map {
EndPointUI(
isActive = activeDevice.endpointName == it.endpointName, it
)
}
}
Pour modifier un appareil actif, utilisez le requestEndpointChange
avec le
CallEndpoint
que vous souhaitez utiliser.
coroutineScope.launch {
callControlScope?.requestEndpointChange(callEndpoint)
}
Compatibilité avec le premier plan
La bibliothèque Telecom prend en charge le premier plan. Cette bibliothèque utilise
ConnectionService
pour les appareils équipés d'Android 13 ou version antérieure. Pour Android 14 et
il utilise le micro et la caméra des types de premier plan pour
sont compatibles avec les services de premier plan. En savoir plus sur les services de premier plan
Conformément aux exigences de premier plan, l'application doit afficher une notification pour que les utilisateurs sachent que l'application s'exécute au premier plan.
Pour vous assurer que votre application dispose de la priorité d'exécution au premier plan, créez un une fois l'appel enregistré auprès de la plate-forme. Priorité au premier plan est supprimé lorsque votre application met fin à l'appel ou que votre notification n'est plus valide.
is TelecomCall.Registered -> {
val notification = createNotification(call)
notificationManager.notify(TELECOM_NOTIFICATION_ID, notification)
}
Compatibilité avec les surfaces
Les montres ont une application de récepteur de point de terminaison générique. Cette application fournit l'utilisateur avec une interface de base (répondre, refuser et déconnecter, par exemple) appels. L'application prend en charge ces actions en implémentant des fonctions lambda indiquant à la plate-forme que vous avez effectué l'action sur l'appareil.
Chaque fonction lambda expire au bout de cinq secondes avec une transaction ayant échoué si votre l'application ne répond pas.
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 = {}