Standard-Telefonanwendung erstellen

Mit einer Standard-Telefon-App kann das Android Telecom-Framework Ihre Anwendung über den Anrufstatus informieren. Dazu verwenden Sie den Rollenmanager und den Dienst während des Anrufs, um einen Ersatz für die Standard-Telefon-App auf einem Android-Gerät zu erstellen und die InCallService API zu implementieren. Ihre Implementierung muss die folgenden Anforderungen erfüllen:

Sie darf keine Aufruffunktion haben und darf ausschließlich die Benutzeroberfläche für den Aufruf umfassen. Er muss alle Anrufe verarbeiten, die dem Framework für Telekommunikation bekannt sind, und es darf keine Annahmen über die Art der Anrufe getroffen werden. Es darf beispielsweise nicht davon ausgegangen werden, dass es sich bei Anrufen um SIM-basierte Telefonieanrufe handelt, und es darf keine Anrufbeschränkungen implementiert werden, die auf einem einzelnen ConnectionService basieren, wie die Erzwingung von Telefonieeinschränkungen für Videoanrufe.

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.

Die Standard-Telefon-App

Die standardmäßige Telefon-/Telefon-App bietet die Benutzeroberfläche während eines Anrufs, während das Gerät während eines Anrufs aktiv ist. Außerdem können Nutzer auf ihrem Gerät Anrufe starten und den Verlauf der Anrufe aufrufen. Ein Gerät ist mit einer vom System bereitgestellten Standard-Telefon-/Telefon-App verknüpft. Der Nutzer kann eine einzelne App auswählen, um diese Rolle in der System-App zu übernehmen. Eine App, die diese Rolle ausüben möchte, verwendet RoleManager, um anzufordern, dass sie die Rolle RoleManager.ROLE_DIALER ausführen.

Die standardmäßige Telefon-App bietet eine Benutzeroberfläche, während das Gerät telefoniert und sich nicht im Automodus befindet (d.h. UiModeManager#getCurrentModeType() ist nicht Configuration.UI_MODE_TYPE_CAR).

Eine Anwendung muss eine Reihe von Anforderungen erfüllen, um die Rolle RoleManager.ROLE_DIALER auszuüben:

  • Er muss den Intent Intent#ACTION_DIAL verarbeiten. Das bedeutet, dass die App eine Benutzeroberfläche für die Wähltasten bereitstellen muss, über die der Nutzer ausgehende Anrufe initiieren kann.
  • Sie muss die InCallService API vollständig implementieren und sowohl eine UI für eingehende als auch eine für laufende Aufrufe bereitstellen.

Hinweis: Wenn die App, die das RoleManager.ROLE_DIALER-Element ausfüllt, während der Bindung ein null-InCallService zurückgibt, verwendet das Telecom-Framework automatisch die auf dem Gerät vorinstallierte Telefon-App. Das System zeigt dem Nutzer eine Benachrichtigung an, um ihn darüber zu informieren, dass sein Anruf über die vorinstallierte Telefon-App fortgesetzt wurde. Deine App sollte niemals eine null-Bindung zurückgeben, da sie dann die Anforderungen von RoleManager.ROLE_DIALER nicht erfüllt.

Hinweis: Wenn deine App RoleManager.ROLE_DIALER ausfüllt und zur Laufzeit Änderungen vornimmt, die dazu führen, dass sie die Anforderungen dieser Rolle nicht mehr erfüllt, entfernt RoleManager deine App automatisch aus der Rolle und schließt deine App. Wenn du beispielsweise PackageManager.setComponentEnabledSetting(ComponentName, int, int) verwendest, um InCallService programmatisch zu deaktivieren, die deine App in ihrem Manifest deklariert, erfüllt deine App nicht mehr die erwarteten Anforderungen von RoleManager.ROLE_DIALER.

Die vorinstallierte Telefon App wird IMMER verwendet, wenn der Nutzer einen Notruf absetzt, auch wenn deine App die Rolle RoleManager.ROLE_DIALER ausfüllt. Um Notrufe optimal abzusetzen, sollte das Standard-Telefon IMMER TelecomManager.placeCall(Uri, Bundle) zum Tätigen von Anrufen (einschließlich Notrufen) verwenden. Dadurch kann die Plattform prüfen, ob die Anfrage vom Standard-Dialer stammt. Wenn eine nicht vorinstallierte Telefon-App Intent#ACTION_CALL zum Tätigen eines Notrufs verwendet, wird dieser zur Bestätigung über Intent#ACTION_DIAL an die vorinstallierte Telefon-App weitergeleitet. Dies ist nicht optimal.

Unten siehst du ein Beispiel für die Manifestregistrierung für einen InCallService. Das Metadaten-TelecomManager#METADATA_IN_CALL_SERVICE_UI gibt an, dass diese spezielle InCallService-Implementierung beabsichtigt, die integrierte UI für den Aufruf zu ersetzen. Die Metadaten TelecomManager#METADATA_IN_CALL_SERVICE_RINGING zeigen an, dass diese InCallService den Klingelton für eingehende Anrufe abspielt. Weiter unten finden Sie weitere Informationen zum Anzeigen der Benutzeroberfläche für eingehende Anrufe und zum Abspielen des Klingeltons in Ihrer App.

 <service android:name="your.package.YourInCallServiceImplementation"
          android:permission="android.permission.BIND_INCALL_SERVICE"
          android:exported="true">
      <meta-data android:name="android.telecom.IN_CALL_SERVICE_UI" android:value="true" />
      <meta-data android:name="android.telecom.IN_CALL_SERVICE_RINGING"
          android:value="true" />
      <intent-filter>
          <action android:name="android.telecom.InCallService"/>
      </intent-filter>
 </service>

Hinweis: Sie sollten InCallService NICHT mit dem Attribut android:exported="false" kennzeichnen, da dies dazu führen kann, dass die Bindung an Ihre Implementierung bei Aufrufen fehlschlägt.

Zusätzlich zur Implementierung der InCallService API musst du in deinem Manifest eine Aktivität deklarieren, die den Intent#ACTION_DIAL-Intent verarbeitet. Das folgende Beispiel veranschaulicht, wie dies funktioniert:

 <activity android:name="your.package.YourDialerActivity"
           android:label="@string/yourDialerActivityLabel">
      <intent-filter>
           <action android:name="android.intent.action.DIAL" />
           <category android:name="android.intent.category.DEFAULT" />
      </intent-filter>
      <intent-filter>
           <action android:name="android.intent.action.DIAL" />
           <category android:name="android.intent.category.DEFAULT" />
           <data android:scheme="tel" />
      </intent-filter>
 </activity>

Wenn ein Nutzer deine Anwendung installiert und zum ersten Mal ausführt, solltest du RoleManager verwenden, um den Nutzer zu fragen, ob deine App die neue Standard-Telefon-App sein soll.

Der folgende Code zeigt, wie Ihre App anfragen kann, die Standard-Telefon-/Dialer-App zu werden:

 private static final int REQUEST_ID = 1;

 public void requestRole() {
     RoleManager roleManager = (RoleManager) getSystemService(ROLE_SERVICE);
     Intent intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_DIALER);
     startActivityForResult(intent, REQUEST_ID);
 }

 public void onActivityResult(int requestCode, int resultCode, Intent data) {
     if (requestCode == REQUEST_ID) {
         if (resultCode == android.app.Activity.RESULT_OK) {
             // Your app is now the default dialer app
         } else {
             // Your app is not the default dialer app
         }
     }
 }

Zugriff auf InCallService für Wearable-Geräte

    Wenn deine App eine Companion-App eines Drittanbieters ist und auf InCallService APIs zugreifen möchte, kann deine App Folgendes tun:

    1. Berechtigung „MANAGE_ONGOING_CALLS“ in Ihrem Manifest deklarieren
    2. Verknüpfung mit einem physischen Wearable über die CompanionDeviceManager API als Companion-App herstellen. Weitere Informationen: https://developer.android.com/guide/topics/connectivity/companion-device-pairing
    3. Diesen InCallService mit der Berechtigung BIND_INCALL_SERVICE implementieren

Benachrichtigung über eingehenden Anruf anzeigen

Wenn die Anwendung einen neuen eingehenden Anruf über InCallService#onCallAdded(Call) empfängt, muss sie die UI für eingehende Anrufe für den eingehenden Anruf anzeigen. Dies sollte mithilfe von NotificationManager APIs erfolgen, um eine neue Benachrichtigung über einen eingehenden Anruf zu posten.

Wenn deine App die Metadaten TelecomManager#METADATA_IN_CALL_SERVICE_RINGING deklariert, ist sie für das Abspielen des Klingeltons bei eingehenden Anrufen verantwortlich. Deine App sollte einen NotificationChannel erstellen, der den gewünschten Klingelton angibt. Beispiele:

 NotificationChannel channel = new NotificationChannel(YOUR_CHANNEL_ID, "Incoming Calls",
          NotificationManager.IMPORTANCE_MAX);
 // other channel setup stuff goes here.

 // We'll use the default system ringtone for our incoming call notification channel.  You can
 // use your own audio resource here.
 Uri ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
 channel.setSound(ringtoneUri, new AudioAttributes.Builder()
          // Setting the AudioAttributes is important as it identifies the purpose of your
          // notification sound.
          .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
          .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
      .build());

 NotificationManager mgr = getSystemService(NotificationManager.class);
 mgr.createNotificationChannel(channel);

Wenn die App einen neuen eingehenden Anruf empfängt, erstellt sie eine Notification für den eingehenden Anruf und verknüpft ihn mit dem Benachrichtigungskanal für eingehende Anrufe. Du kannst in der Benachrichtigung ein PendingIntent angeben, das die Benutzeroberfläche für eingehende Anrufe im Vollbildmodus öffnet. Im Framework des Benachrichtigungsmanagers wird deine Benachrichtigung als Vorabbenachrichtigung angezeigt, wenn der Nutzer das Smartphone aktiv verwendet. Wenn der Nutzer das Smartphone nicht verwendet, wird stattdessen die Benutzeroberfläche für eingehende Anrufe im Vollbildmodus verwendet. Beispiele:

 // Create an intent which triggers your fullscreen incoming call user interface.
 Intent intent = new Intent(Intent.ACTION_MAIN, null);
 intent.setFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION | Intent.FLAG_ACTIVITY_NEW_TASK);
 intent.setClass(context, YourIncomingCallActivity.class);
 PendingIntent pendingIntent = PendingIntent.getActivity(context, 1, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
 // Build the notification as an ongoing high priority item; this ensures it will show as
 // a heads up notification which slides down over top of the current content.
 final Notification.Builder builder = new Notification.Builder(context);
 builder.setOngoing(true);
 builder.setPriority(Notification.PRIORITY_HIGH);
 // Set notification content intent to take user to the fullscreen UI if user taps on the
 // notification body.
 builder.setContentIntent(pendingIntent);
 // Set full screen intent to trigger display of the fullscreen UI when the notification
 // manager deems it appropriate.
 builder.setFullScreenIntent(pendingIntent, true);
 // Setup notification content.
 builder.setSmallIcon( yourIconResourceId );
 builder.setContentTitle("Your notification title");
 builder.setContentText("Your notification content.");
 // Use builder.addAction(..) to add buttons to answer or reject the call.
 NotificationManager notificationManager = mContext.getSystemService(
     NotificationManager.class);
 notificationManager.notify(YOUR_CHANNEL_ID, YOUR_TAG, YOUR_ID, builder.build());
```