Anruf-App entwickeln

Mit einer Anruf-App können Nutzer Audio- oder Videoanrufe auf ihrem Gerät annehmen oder tätigen. Anruf-Apps verwenden für die Anrufe eine eigene Benutzeroberfläche anstelle der Standardoberfläche der Telefon App, wie im folgenden Screenshot dargestellt.

Beispiel für eine Anruf-App
Beispiel für eine Anruf-App mit eigener Benutzeroberfläche

Das Android-Framework enthält das Paket android.telecom mit Klassen, mit denen Sie eine aufrufende App gemäß dem Telekommunikations-Framework erstellen können. Das Erstellen Ihrer Anwendung gemäß dem Telekommunikations-Framework bietet folgende Vorteile:

  • Ihre Anwendung arbeitet korrekt mit dem nativen Telekommunikationssubsystem des Geräts zusammen.
  • Ihre App interagiert ordnungsgemäß mit anderen aufrufenden Apps, die ebenfalls dem Framework entsprechen.
  • Das Framework unterstützt Ihre App bei der Verwaltung des Audio- und Videoroutings.
  • Mithilfe des Frameworks kann Ihre App feststellen, ob die Aufrufe fokussiert sind.

Manifestdeklarationen und Berechtigungen

Geben Sie in Ihrem App-Manifest an, dass Ihre App die Berechtigung MANAGE_OWN_CALLS verwendet, wie im folgenden Beispiel gezeigt:

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

Weitere Informationen zum Deklarieren von App-Berechtigungen findest du unter Berechtigungen.

Sie müssen einen Dienst deklarieren, der die Klasse angibt, die die Klasse ConnectionService in Ihrer App implementiert. Das Telekommunikationssubsystem erfordert, dass der Dienst die Berechtigung BIND_TELECOM_CONNECTION_SERVICE deklariert, um eine Bindung daran vornehmen zu können. Das folgende Beispiel zeigt, wie Sie den Dienst in Ihrem App-Manifest deklarieren:

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

Weitere Informationen zum Deklarieren von Anwendungskomponenten, einschließlich Diensten, finden Sie unter Anwendungskomponenten.

Verbindungsdienst implementieren

Die aufrufende App muss eine Implementierung der ConnectionService-Klasse bereitstellen, an die das Telekommunikationssubsystem gebunden werden kann. Die Implementierung von ConnectionService sollte die folgenden Methoden überschreiben:

onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)

Das Telekommunikationssubsystem ruft diese Methode als Reaktion darauf auf, dass Ihre Anwendung placeCall(Uri, Bundle) aufruft, um einen neuen ausgehenden Aufruf zu erstellen. Die Anwendung gibt eine neue Instanz der Connection-Klassenimplementierung zurück (weitere Informationen unter Verbindung implementieren), um den neuen ausgehenden Aufruf darzustellen. Sie können die ausgehende Verbindung weiter anpassen, indem Sie die folgenden Aktionen ausführen:

onCreateOutgoingConnectionFailed(PhoneAccountHandle, ConnectionRequest)

Das Telekommunikationssubsystem ruft diese Methode auf, wenn Ihre Anwendung die Methode placeCall(Uri, Bundle) aufruft und der ausgehende Aufruf nicht ausgeführt werden kann. In diesem Fall sollte Ihre Anwendung den Nutzer (z. B. mit einem Benachrichtigungsfeld oder einem Toast) darüber informieren, dass der ausgehende Anruf nicht getätigt werden konnte. Bei einem laufenden Notfall oder bei einem laufenden Anruf in einer anderen App, der vor dem Tätigen des Anrufs nicht in die Warteschleife gelegt werden kann, kann die App möglicherweise keine Anrufe tätigen.

onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)

Das Telekommunikationssubsystem ruft diese Methode auf, wenn Ihre Anwendung die Methode addNewIncomingCall(PhoneAccountHandle, Bundle) aufruft, um das System über einen neuen eingehenden Aufruf in Ihrer Anwendung zu informieren. Ihre Anwendung gibt eine neue Instanz Ihrer Connection-Implementierung zurück (weitere Informationen finden Sie unter Verbindung implementieren), um den neuen eingehenden Aufruf darzustellen. Sie können die eingehende Verbindung weiter anpassen, indem Sie die folgenden Aktionen ausführen:

onCreateIncomingConnectionFailed(PhoneAccountHandle, ConnectionRequest)

Das Telekommunikationssubsystem ruft diese Methode auf, wenn Ihre Anwendung die Methode addNewIncomingCall(PhoneAccountHandle, Bundle) aufruft, um Telecom über einen neuen eingehenden Anruf zu informieren. Der eingehende Anruf ist jedoch nicht zulässig. Weitere Informationen finden Sie unter Einschränkungen für Aufrufe. Ihre App sollte den eingehenden Anruf stumm ablehnen und den Nutzer optional mit einer Benachrichtigung über den verpassten Anruf informieren.

Verbindung implementieren

Ihre Anwendung sollte eine abgeleitete Klasse von Connection erstellen, um die Aufrufe in Ihrer Anwendung darzustellen. Sie sollten die folgenden Methoden in Ihrer Implementierung überschreiben:

onShowIncomingCallUi()

Das Telekommunikationssubsystem ruft diese Methode auf, wenn Sie einen neuen eingehenden Anruf hinzufügen und die Anwendung die UI für eingehende Anrufe anzeigen sollte.

onCallAudioStateChanged(CallAudioState)

Das Telekommunikationssubsystem ruft diese Methode auf, um Ihre App darüber zu informieren, dass sich die aktuelle Audioroute oder der aktuelle Audiomodus geändert hat. Dieser wird als Reaktion darauf aufgerufen, dass Ihre Anwendung den Audiomodus mit der Methode setAudioRoute(int) ändert. Diese Methode kann auch aufgerufen werden, wenn das System die Audioroute ändert, z. B. wenn die Verbindung eines Bluetooth-Headsets getrennt wird.

onHold()

Das Telekommunikationssubsystem ruft diese Methode auf, wenn ein Anruf gehalten werden soll. Als Antwort auf diese Anfrage sollte Ihre App den Aufruf halten und dann die Methode setOnHold() aufrufen, um das System darüber zu informieren, dass der Anruf gehalten wird. Das Telekommunikationssubsystem kann diese Methode aufrufen, wenn ein Anrufdienst wie Android Auto, der deinen Anruf anzeigt, eine Nutzeranfrage weiterleiten möchte, um den Anruf zu halten. Das Telekommunikationssubsystem ruft diese Methode auch dann auf, wenn der Nutzer einen Aufruf in einer anderen Anwendung aktiviert. Weitere Informationen zu Diensten während des Anrufs finden Sie unter InCallService.

onUnhold()

Das Telekommunikationssubsystem ruft diese Methode auf, wenn ein angehaltener Anruf fortgesetzt werden soll. Sobald Ihre App den Aufruf fortgesetzt hat, sollte sie die Methode setActive() aufrufen, um das System darüber zu informieren, dass der Aufruf nicht mehr gehalten wird. Das Telekommunikationssubsystem kann diese Methode aufrufen, wenn ein im Anruf befindlicher Dienst wie Android Auto, der Ihren Anruf anzeigt, eine Anfrage zum Fortsetzen des Anrufs weiterleiten möchte. Weitere Informationen zu Diensten während des Anrufs finden Sie unter InCallService.

onAnswer()

Das Telekommunikationssubsystem ruft diese Methode auf, um Ihre App darüber zu informieren, dass ein eingehender Anruf angenommen werden soll. Sobald Ihre App den Aufruf angenommen hat, sollte die Methode setActive() aufgerufen werden, um das System darüber zu informieren, dass der Aufruf angenommen wurde. Das Telekommunikationssubsystem kann diese Methode aufrufen, wenn Ihre App einen neuen eingehenden Anruf hinzufügt und in einer anderen App bereits ein Anruf läuft, der nicht auf „Halten“ gesetzt werden kann. Das Telekommunikationssubsystem zeigt in diesen Instanzen die UI für eingehende Anrufe im Namen Ihrer Anwendung an. Das Framework bietet eine überlastete Methode, mit der der Videostatus angegeben werden kann, in dem der Anruf angenommen werden soll. Weitere Informationen finden Sie unter onAnswer(int).

onReject()

Das Telekommunikationssubsystem ruft diese Methode auf, wenn ein eingehender Anruf abgelehnt werden soll. Sobald Ihre App den Aufruf abgelehnt hat, sollte setDisconnected(DisconnectCause) aufgerufen und REJECTED als Parameter angegeben werden. Ihre App sollte dann die Methode destroy() aufrufen, um das System darüber zu informieren, dass die App den Aufruf verarbeitet hat. Das Telekommunikationssubsystem ruft diese Methode auf, wenn der Nutzer einen eingehenden Anruf von Ihrer Anwendung abgelehnt hat.

onDisconnect()

Das Telekommunikationssubsystem ruft diese Methode auf, wenn ein Anruf getrennt werden soll. Sobald der Aufruf beendet ist, sollte Ihre App die Methode setDisconnected(DisconnectCause) aufrufen und LOCAL als Parameter angeben, um anzugeben, dass die Verbindung des Aufrufs aufgrund einer Nutzeranfrage getrennt wurde. Ihre App sollte dann die Methode destroy() aufrufen, um das Telekommunikationssubsystem darüber zu informieren, dass die App den Aufruf verarbeitet hat. Das System kann diese Methode aufrufen, wenn der Nutzer einen Anruf über einen anderen Dienst während des Anrufs getrennt hat, z. B. Android Auto. Das System ruft diese Methode auch auf, wenn die Verbindung des Anrufs getrennt werden muss, damit andere Anrufe getätigt werden können, z. B. wenn der Nutzer einen Notruf absetzen möchte. Weitere Informationen zu Diensten während eines Anrufs finden Sie unter InCallService.

Häufige Anrufszenarien verarbeiten

Wenn Sie die ConnectionService API in Ihrem Aufrufablauf verwenden, interagieren Sie mit den anderen Klassen im Paket android.telecom. In den folgenden Abschnitten werden gängige Aufrufszenarien und die dafür vorgesehenen APIs in Ihrer Anwendung beschrieben.

Eingehende Anrufe annehmen

Der Ablauf zur Verarbeitung eingehender Anrufe ändert sich unabhängig davon, ob Anrufe in anderen Apps stattfinden oder nicht. Der Grund für den Unterschied zwischen den Abläufen besteht darin, dass das Telekommunikations-Framework einige Einschränkungen festlegen muss, wenn aktive Aufrufe in anderen Apps vorhanden sind, um eine stabile Umgebung für alle aufrufenden Apps auf dem Gerät zu gewährleisten. Weitere Informationen finden Sie unter Aufrufeinschränkungen.

Keine aktiven Anrufe in anderen Apps

So kannst du eingehende Anrufe annehmen, während keine aktiven Anrufe in anderen Apps aktiv sind:

  1. Ihre App empfängt neue eingehende Anrufe mit den üblichen Methoden.
  2. Mit der Methode addNewIncomingCall(PhoneAccountHandle, Bundle) informieren Sie das Telekommunikationssubsystem über den neuen eingehenden Anruf.
  3. Das Telekommunikationssubsystem bindet sich an die Implementierung ConnectionService Ihrer Anwendung und fordert mit der Methode onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest) eine neue Instanz der Klasse Connection an, die den neuen eingehenden Aufruf darstellt.
  4. Das Telekommunikationssubsystem teilt der Anwendung mit, dass die Benutzeroberfläche für eingehende Anrufe mithilfe der Methode onShowIncomingCallUi() angezeigt werden soll.
  5. Ihre App zeigt die eingehende UI über eine Benachrichtigung mit einem verknüpften Full-Screen-Intent an. Weitere Informationen findest du unter onShowIncomingCallUi().
  6. Rufen Sie die Methode setActive() auf, wenn der Nutzer den eingehenden Anruf annimmt, oder rufen Sie die Methode setDisconnected(DisconnectCause) auf, indem Sie REJECTED als Parameter angeben, gefolgt von einem Aufruf der Methode destroy(), wenn der Nutzer den eingehenden Anruf ablehnt.

Aktive Anrufe in anderen Apps, die nicht gehalten werden können

So nehmen Sie eingehende Anrufe an, während es aktive Anrufe in anderen Apps gibt, die nicht gehalten werden können:

  1. Ihre App empfängt neue eingehende Anrufe mit den üblichen Methoden.
  2. Mit der Methode addNewIncomingCall(PhoneAccountHandle, Bundle) informieren Sie das Telekommunikationssubsystem über den neuen eingehenden Anruf.
  3. Das Telekommunikationssubsystem bindet sich an die ConnectionService-Implementierung Ihrer Anwendung und fordert mit der Methode onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest) eine neue Instanz des Connection-Objekts an, das den neuen eingehenden Aufruf darstellt.
  4. Das Telekommunikationssubsystem zeigt die Benutzeroberfläche für eingehende Anrufe für Ihren eingehenden Anruf an.
  5. Wenn der Nutzer den Aufruf annimmt, ruft das Telekommunikationssubsystem die Methode onAnswer() auf. Sie sollten die Methode setActive() aufrufen, um dem Telekommunikationssubsystem zu signalisieren, dass der Aufruf jetzt verbunden ist.
  6. Wenn der Nutzer den Aufruf ablehnt, ruft das Telekommunikationssubsystem die Methode onReject() auf. Sie sollten die Methode setDisconnected(DisconnectCause) aufrufen und REJECTED als Parameter angeben, gefolgt von einem Aufruf der Methode destroy().

Ausgehende Anrufe tätigen

Der Ablauf zum Tätigen eines ausgehenden Anrufs beinhaltet die Möglichkeit, dass der Aufruf aufgrund von Einschränkungen, die vom Telekommunikations-Framework auferlegt werden, nicht getätigt werden kann. Weitere Informationen finden Sie unter Aufrufeinschränkungen.

So können Sie einen ausgehenden Anruf tätigen:

  1. Der Nutzer initiiert einen ausgehenden Anruf in Ihrer App.
  2. Verwenden Sie die Methode placeCall(Uri, Bundle), um das Telekommunikationssubsystem über den neuen ausgehenden Anruf zu informieren. Beachten Sie bei den Methodenparametern Folgendes:
    • Der Parameter Uri steht für die Adresse, an die der Aufruf gesendet wird. Verwenden Sie für normale Telefonnummern das URI-Schema tel:.
    • Mit dem Parameter Bundle können Sie Informationen zu Ihrer aufrufenden App angeben. Dazu fügen Sie das PhoneAccountHandle-Objekt Ihrer App zum EXTRA_PHONE_ACCOUNT_HANDLE-Extra hinzu. Ihre App muss bei jedem ausgehenden Anruf das Objekt PhoneAccountHandle bereitstellen.
    • Mit dem Parameter Bundle können Sie auch angeben, ob der ausgehende Anruf Video umfasst. Dazu geben Sie den Wert STATE_BIDIRECTIONAL im zusätzlichen EXTRA_START_CALL_WITH_VIDEO_STATE an. Beachten Sie, dass das Telekommunikationssubsystem Videoanrufe standardmäßig an die Freisprechfunktion weiterleitet.
  3. Das Telekommunikationssubsystem bindet sich an die ConnectionService-Implementierung Ihrer Anwendung.
  4. Wenn Ihre Anwendung keine ausgehenden Anrufe tätigen kann, ruft das Telekommunikationssubsystem die Methode onCreateOutgoingConnectionFailed(PhoneAccountHandle, ConnectionRequest) auf, um die Anwendung zu informieren, dass der Aufruf zum aktuellen Zeitpunkt nicht möglich ist. Der Nutzer sollte in der App darüber informiert werden, dass der Anruf nicht möglich ist.
  5. Wenn Ihre Anwendung den ausgehenden Aufruf ausführen kann, ruft das Telekommunikationssubsystem die Methode onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest) auf. Die App sollte eine Instanz der Connection-Klasse zurückgeben, die den neuen ausgehenden Anruf darstellt. Weitere Informationen zu den Attributen, die in der Verbindung festgelegt werden sollten, finden Sie unter Verbindungsdienst implementieren.
  6. Wenn der ausgehende Anruf verbunden wurde, rufen Sie die Methode setActive() auf, um das Telekommunikationssubsystem darüber zu informieren, dass der Aufruf aktiv ist.

Anruf beenden

So beenden Sie einen Anruf:

  1. Rufen Sie das setDisconnected(DisconnectCause) auf, das LOCAL als Parameter sendet, wenn der Nutzer den Aufruf beendet hat, oder REMOTE als Parameter, wenn die andere Partei den Aufruf beendet hat.
  2. Rufen Sie die Methode destroy() auf.

Aufrufeinschränkungen

Um eine einheitliche und einfache Anruferfahrung für Ihre Nutzer zu gewährleisten, erzwingt das Telekommunikations-Framework einige Einschränkungen für die Verwaltung von Anrufen auf dem Gerät. Angenommen, der Nutzer hat zwei aufrufende Apps installiert, die die selbstverwaltete ConnectionService API implementieren, nämlich FooTalk und BarTalk. In diesem Fall gelten die folgenden Einschränkungen:

  • Auf Geräten mit API-Level 27 oder niedriger kann jeweils nur eine App einen laufenden Aufruf aufrechterhalten. Diese Einschränkung bedeutet, dass ein Nutzer während eines laufenden Anrufs mit der FooTalk-App keinen neuen Anruf initiieren oder empfangen kann.

    Wenn auf Geräten mit API-Level 28 oder höher sowohl FooTalk als auch BarTalk die Berechtigungen CAPABILITY_SUPPORT_HOLD und CAPABILITY_HOLD deklariert, kann der Nutzer mehr als einen laufenden Anruf aufrechterhalten, indem er zwischen den Apps wechselt, um einen weiteren Anruf zu initiieren oder anzunehmen.

  • Wenn der Nutzer regelmäßige verwaltete Anrufe tätigt (z. B. über die integrierte Telefon App oder Telefon App), kann er nicht an Anrufen teilnehmen, die aus Anruf-Apps stammen. Das bedeutet, dass ein Nutzer, der über seinen Mobilfunkanbieter verbunden ist, nicht gleichzeitig an einem FooTalk- oder BarTalk-Anruf teilnehmen kann.

  • Das Telekommunikationssubsystem trennt die Anrufe Ihrer App, wenn der Nutzer einen Notruf tätigt.

  • Solange der Nutzer einen Notruf absetzt, kann die App keine Anrufe empfangen oder tätigen.

  • Wenn während eines eingehenden Anrufs in der anderen Anruf-App ein laufender Anruf in der App eingeht, werden durch die Annahme des eingehenden Anrufs alle laufenden Anrufe in der anderen App beendet. In der App sollte nicht die normale Benutzeroberfläche für eingehende Anrufe angezeigt werden. Das Telekommunikations-Framework zeigt die Benutzeroberfläche für eingehende Anrufe an und informiert den Nutzer, dass durch Annehmen des neuen Anrufs die laufenden Anrufe beendet werden. Wenn der Nutzer also an einem FooTalk-Anruf teilnimmt und die BarTalk-App einen eingehenden Anruf empfängt, informiert das Telekommunikations-Framework den Nutzer darüber, dass er einen neuen eingehenden BarTalk-Anruf hat und dass er durch Annehmen des BarTalk-Anrufs beendet wird.