Développer une application d'appel

Une application d'appel permet aux utilisateurs de recevoir ou de passer des appels audio ou vidéo sur leur appareil. Les applications d'appel utilisent leur propre interface utilisateur pour les appels au lieu de l'interface par défaut de l'application Téléphone, comme illustré dans la capture d'écran suivante.

Exemple d'application d'appel
Exemple d'application appelante utilisant sa propre interface utilisateur

Le framework Android inclut le package android.telecom, qui contient des classes qui vous aident à créer une application appelante en fonction du framework de télécommunications. Concevoir votre application conformément au framework pour les télécommunications offre les avantages suivants:

  • Votre application interagit correctement avec le sous-système de télécommunications natif de l'appareil.
  • Votre application interagit correctement avec d'autres applications appelantes qui respectent également le framework.
  • Le framework aide votre application à gérer le routage audio et vidéo.
  • Le framework aide votre application à déterminer si ses appels sont ciblés.

Déclarations et autorisations relatives au fichier manifeste

Dans le fichier manifeste de votre application, déclarez que celle-ci utilise l'autorisation MANAGE_OWN_CALLS, comme indiqué dans l'exemple suivant:

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

Pour en savoir plus sur la déclaration d'autorisations d'application, consultez la section Autorisations.

Vous devez déclarer un service qui spécifie la classe qui implémente la classe ConnectionService dans votre application. Le sous-système de télécommunications exige que le service déclare l'autorisation BIND_TELECOM_CONNECTION_SERVICE pour pouvoir s'y associer. L'exemple suivant montre comment déclarer le service dans le fichier manifeste de votre application:

<service android:name="com.example.MyConnectionService"
    android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE">
    <intent-filter>
        <action android:name="android.telecom.ConnectionService" />
    </intent-filter>
</service>

Pour en savoir plus sur la déclaration de composants d'application, y compris les services, consultez la section Composants d'application.

Implémenter le service de connexion

Votre application appelante doit fournir une implémentation de la classe ConnectionService à laquelle le sous-système de télécommunications peut être lié. Votre implémentation de ConnectionService doit remplacer les méthodes suivantes:

onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)

Le sous-système de télécommunications appelle cette méthode en réponse à l'appel de placeCall(Uri, Bundle) par votre application pour créer un appel sortant. Votre application renvoie une nouvelle instance de l'implémentation de votre classe Connection (pour en savoir plus, consultez Implémenter la connexion) pour représenter le nouvel appel sortant. Vous pouvez personnaliser davantage la connexion sortante en effectuant les actions suivantes:

onCreateOutgoingConnectionFailed(PhoneAccountHandle, ConnectionRequest)

Le sous-système de télécommunications appelle cette méthode lorsque votre application appelle la méthode placeCall(Uri, Bundle) et que l'appel sortant ne peut pas être passé. Dans ce cas, votre application doit informer l'utilisateur (par exemple, à l'aide d'une zone d'alerte ou d'un toast) que l'appel sortant n'a pas pu être passé. Il est possible que votre application ne puisse pas passer d'appel si un appel d'urgence est en cours ou si un appel en cours dans une autre application ne peut pas être mis en attente avant de passer votre appel.

onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)

Le sous-système de télécommunications appelle cette méthode lorsque votre application appelle la méthode addNewIncomingCall(PhoneAccountHandle, Bundle) pour informer le système d'un nouvel appel entrant dans votre application. Votre application renvoie une nouvelle instance de votre implémentation de Connection (pour en savoir plus, consultez Implémenter la connexion) pour représenter le nouvel appel entrant. Vous pouvez personnaliser davantage la connexion entrante en effectuant les actions suivantes:

onCreateIncomingConnectionFailed(PhoneAccountHandle, ConnectionRequest)

Le sous-système de télécommunications appelle cette méthode lorsque votre application appelle la méthode addNewIncomingCall(PhoneAccountHandle, Bundle) pour informer Telecom d'un nouvel appel entrant, mais que cet appel n'est pas autorisé (pour en savoir plus, consultez la section Contraintes d'appel). Votre application doit rejeter l'appel entrant en silence, en publiant éventuellement une notification pour informer l'utilisateur de l'appel manqué.

Implémenter la connexion

Votre application doit créer une sous-classe de Connection pour représenter les appels. Vous devez remplacer les méthodes suivantes dans votre implémentation:

onShowIncomingCallUi()

Le sous-système de télécommunications appelle cette méthode lorsque vous ajoutez un appel entrant. Votre application doit afficher son UI d'appel entrant.

onCallAudioStateChanged(CallAudioState)

Le sous-système de télécommunications appelle cette méthode pour informer votre application que la route ou le mode audio actuel a changé. Cette méthode est appelée lorsque votre application modifie le mode audio à l'aide de la méthode setAudioRoute(int). Cette méthode peut également être appelée si le système modifie la route audio (par exemple, lorsqu'un casque Bluetooth se déconnecte).

onHold()

Le sous-système de télécommunications appelle cette méthode lorsqu'il souhaite mettre un appel en attente. En réponse à cette requête, votre application doit mettre l'appel en attente, puis appeler la méthode setOnHold() pour informer le système que l'appel est en attente. Le sous-système de télécommunications peut appeler cette méthode lorsqu'un service en cours d'appel, tel qu'Android Auto, qui montre que votre appel souhaite transmettre une requête utilisateur visant à mettre l'appel en attente. Le sous-système de télécommunications appelle également cette méthode si l'utilisateur effectue un appel actif dans une autre application. Pour en savoir plus sur les services en cours d'appel, consultez InCallService.

onUnhold()

Le sous-système de télécommunications appelle cette méthode lorsqu'il souhaite reprendre un appel mis en attente. Une fois que votre application a repris l'appel, elle doit appeler la méthode setActive() pour informer le système que l'appel n'est plus en attente. Le sous-système de télécommunications peut appeler cette méthode lorsqu'un service en cours d'appel, tel qu'Android Auto, qui montre que votre appel souhaite transmettre une requête pour reprendre l'appel. Pour en savoir plus sur les services en cours d'appel, consultez InCallService.

onAnswer()

Le sous-système de télécommunications appelle cette méthode pour informer votre application qu'un appel entrant doit être traité. Une fois que votre application a répondu à l'appel, elle doit appeler la méthode setActive() pour informer le système que la réponse a été obtenue. Le sous-système de télécommunications peut appeler cette méthode lorsque votre application ajoute un nouvel appel entrant et qu'un appel en cours dans une autre application ne peut pas être mis en attente. Dans ce cas, le sous-système de télécommunications affiche l'UI des appels entrants pour le compte de votre application. Le framework fournit une méthode surchargée qui permet de spécifier l'état de la vidéo dans lequel répondre à l'appel. Pour en savoir plus, consultez onAnswer(int).

onReject()

Le sous-système de télécommunications appelle cette méthode lorsqu'il souhaite rejeter un appel entrant. Une fois que votre application a refusé l'appel, elle doit appeler setDisconnected(DisconnectCause) et spécifier REJECTED comme paramètre. Votre application doit ensuite appeler la méthode destroy() pour informer le système qu'elle a traité l'appel. Le sous-système de télécommunications appelle cette méthode lorsque l'utilisateur a rejeté un appel entrant de votre application.

onDisconnect()

Le sous-système de télécommunications appelle cette méthode lorsqu'il souhaite mettre fin à un appel. Une fois l'appel terminé, votre application doit appeler la méthode setDisconnected(DisconnectCause) et spécifier LOCAL comme paramètre pour indiquer qu'une requête utilisateur a entraîné la déconnexion de l'appel. Votre application doit ensuite appeler la méthode destroy() pour informer le sous-système de télécommunications que l'application a traité l'appel. Le système peut appeler cette méthode lorsque l'utilisateur a déconnecté un appel via un autre service en cours d'appel, tel qu'Android Auto. Le système appelle également cette méthode lorsque votre appel doit être déconnecté pour permettre un autre appel, par exemple si l'utilisateur souhaite passer un appel d'urgence. Pour en savoir plus sur les services en cours d'appel, consultez InCallService.

Gérer les scénarios d'appel courants

L'utilisation de l'API ConnectionService dans votre flux d'appel implique l'interaction avec les autres classes du package android.telecom. Les sections suivantes décrivent les scénarios d'appel courants et la manière dont votre application doit utiliser les API pour les gérer.

Répondre aux appels entrants

Le flux de gestion des appels entrants varie selon qu'il existe des appels dans d'autres applications ou non. La différence entre les flux s'explique par le fait que le framework de télécommunications doit établir certaines contraintes en cas d'appels actifs dans d'autres applications, afin de garantir un environnement stable pour toutes les applications appelantes sur l'appareil. Pour en savoir plus, consultez la section Contraintes d'appel.

Aucun appel en cours dans les autres applis

Pour répondre aux appels entrants lorsqu'il n'y a pas d'appels actifs dans d'autres applications, procédez comme suit:

  1. Votre application reçoit un nouvel appel entrant à l'aide de ses mécanismes habituels.
  2. Utilisez la méthode addNewIncomingCall(PhoneAccountHandle, Bundle) pour informer le sous-système de télécommunications du nouvel appel entrant.
  3. Le sous-système de télécommunications se lie à l'implémentation ConnectionService de votre application et demande une nouvelle instance de la classe Connection représentant le nouvel appel entrant à l'aide de la méthode onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest).
  4. Le sous-système de télécommunications informe votre application qu'elle doit afficher l'interface utilisateur des appels entrants à l'aide de la méthode onShowIncomingCallUi().
  5. Votre application affiche son UI entrante à l'aide d'une notification avec un intent plein écran associé. Pour en savoir plus, consultez onShowIncomingCallUi().
  6. Appelez la méthode setActive() si l'utilisateur accepte l'appel entrant, ou setDisconnected(DisconnectCause) spécifiant REJECTED comme paramètre suivi d'un appel à la méthode destroy() si l'utilisateur refuse l'appel entrant.

Appels actifs dans d'autres applications ne pouvant pas être mis en attente

Pour répondre aux appels entrants lorsque des appels actifs dans d'autres applications ne peuvent pas être mis en attente, procédez comme suit:

  1. Votre application reçoit un nouvel appel entrant à l'aide de ses mécanismes habituels.
  2. Utilisez la méthode addNewIncomingCall(PhoneAccountHandle, Bundle) pour informer le sous-système de télécommunications du nouvel appel entrant.
  3. Le sous-système de télécommunications se lie à l'implémentation ConnectionService de votre application et demande une nouvelle instance de l'objet Connection représentant le nouvel appel entrant à l'aide de la méthode onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest).
  4. Le sous-système de télécommunications affiche l'interface utilisateur de votre appel entrant.
  5. Si l'utilisateur accepte l'appel, le sous-système de télécommunications appelle la méthode onAnswer(). Vous devez appeler la méthode setActive() pour indiquer au sous-système de télécommunications que l'appel est maintenant connecté.
  6. Si l'utilisateur rejette l'appel, le sous-système de télécommunications appelle la méthode onReject(). Vous devez appeler la méthode setDisconnected(DisconnectCause) en spécifiant REJECTED comme paramètre, puis un appel à la méthode destroy().

Passer des appels sortants

Le flux de passage d'un appel sortant implique de gérer la possibilité que l'appel ne puisse pas être passé en raison des contraintes imposées par le framework de télécommunications. Pour en savoir plus, consultez la section Contraintes d'appel.

Pour passer un appel sortant, procédez comme suit:

  1. L'utilisateur passe un appel sortant dans votre application.
  2. Utilisez la méthode placeCall(Uri, Bundle) pour informer le sous-système de télécommunications du nouvel appel sortant. Tenez compte des points suivants concernant les paramètres de méthode :
    • Le paramètre Uri représente l'adresse à laquelle l'appel est passé. Pour les numéros de téléphone standards, utilisez le schéma d'URI tel:.
    • Le paramètre Bundle vous permet de fournir des informations sur votre application appelante en ajoutant l'objet PhoneAccountHandle de votre application à l'extra EXTRA_PHONE_ACCOUNT_HANDLE. Votre application doit fournir l'objet PhoneAccountHandle à chaque appel sortant.
    • Le paramètre Bundle vous permet également de spécifier si l'appel sortant inclut une vidéo en spécifiant la valeur STATE_BIDIRECTIONAL dans l'extra EXTRA_START_CALL_WITH_VIDEO_STATE. Notez que par défaut, le sous-système de télécommunications achemine les appels vidéo vers le haut-parleur.
  3. Le sous-système de télécommunications est lié à l'implémentation ConnectionService de votre application.
  4. Si votre application ne peut pas passer d'appel sortant, le sous-système de télécommunications appelle la méthode onCreateOutgoingConnectionFailed(PhoneAccountHandle, ConnectionRequest) pour indiquer à votre application que l'appel ne peut pas être passé pour l'heure actuelle. Votre application doit informer l'utilisateur que l'appel ne peut pas être passé.
  5. Si votre application peut passer l'appel sortant, le sous-système de télécommunications appelle la méthode onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest). Votre application doit renvoyer une instance de votre classe Connection pour représenter le nouvel appel sortant. Pour en savoir plus sur les propriétés à définir dans la connexion, consultez la section Implémenter le service de connexion.
  6. Une fois l'appel sortant connecté, appelez la méthode setActive() pour informer le sous-système de télécommunications que l'appel est actif.

Mettre fin à un appel

Pour mettre fin à un appel, procédez comme suit:

  1. Appelez la méthode setDisconnected(DisconnectCause) en envoyant LOCAL comme paramètre si l'utilisateur a mis fin à l'appel, ou envoyez REMOTE en tant que paramètre si l'autre partie a mis fin à l'appel.
  2. Appelez la méthode destroy().

Contraintes liées aux appels

Pour garantir une expérience d'appel simple et cohérente à vos utilisateurs, le framework de télécommunications applique certaines contraintes pour la gestion des appels sur l'appareil. Par exemple, imaginons que l'utilisateur a installé deux applications appelantes qui implémentent l'API ConnectionService autogérée : FooTalk et BarTalk. Dans ce cas, les contraintes suivantes s'appliquent:

  • Sur les appareils équipés d'un niveau d'API 27 ou inférieur, une seule application peut maintenir un appel en cours à la fois. Cette contrainte signifie que lorsqu'un utilisateur passe un appel en cours à l'aide de l'application FooTalk, celle-ci ne peut pas initier ni recevoir de nouvel appel.

    Sur les appareils équipés d'un niveau d'API 28 ou supérieur, si FooTalk et BarTalk déclarent les autorisations CAPABILITY_SUPPORT_HOLD et CAPABILITY_HOLD, l'utilisateur peut maintenir plusieurs appels en cours en basculant entre les applications pour initier ou répondre à un autre appel.

  • S'il participe à des appels gérés standards (par exemple, à l'aide de l'application Téléphone ou Téléphone intégrée), il ne peut pas participer à des appels provenant d'applications appelantes. Cela signifie que si l'utilisateur participe à un appel standard via son opérateur mobile, il ne peut pas participer simultanément à un appel FooTalk ou BarTalk.

  • Le sous-système de télécommunications déconnecte les appels de votre application si l'utilisateur compose un appel d'urgence.

  • Votre application ne peut pas recevoir ni passer d'appels pendant un appel d'urgence de l'utilisateur.

  • Si un appel est en cours dans une autre application appelante lorsque votre application reçoit un appel entrant, la réponse à l'appel entrant met fin à tous les appels en cours dans l'autre application. Votre application ne doit pas afficher son interface utilisateur d'appel entrant habituelle. Le framework de télécommunications affiche l'interface utilisateur de l'appel entrant et informe l'utilisateur que le fait de répondre au nouvel appel mettra fin à son ou ses appels en cours. Cela signifie que si l'utilisateur participe à un appel FooTalk et que l'application BarTalk reçoit un appel entrant, le framework de télécommunication informe l'utilisateur qu'il a un nouvel appel BarTalk entrant et que la réponse à l'appel BarTalk mettra fin à son appel FooTalk.