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.
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 derConnection
-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:- Ihre Anwendung sollte die Methode
setConnectionProperties(int)
mit der KonstantePROPERTY_SELF_MANAGED
als Argument aufrufen, um anzugeben, dass die Verbindung von einer aufrufenden Anwendung stammt. - Wenn Ihre Anwendung das Halten von Aufrufen unterstützt, rufen Sie die Methode
setConnectionCapabilities(int)
auf und legen Sie das Argument auf den Bitmaskenwert der KonstantenCAPABILITY_HOLD
undCAPABILITY_SUPPORT_HOLD
fest. - Verwenden Sie zum Festlegen des Namens des Aufrufs die Methode
setCallerDisplayName(String, int)
und übergeben Sie diePRESENTATION_ALLOWED
-Konstante alsint
-Parameter, um anzugeben, dass der Name des Aufrufers angezeigt werden soll. - Damit der ausgehende Aufruf den richtigen Videostatus hat, rufen Sie die Methode
setVideoState(int)
desConnection
-Objekts auf und senden Sie den Wert, der von dergetVideoState()
-Methode desConnectionRequest
-Objekts zurückgegeben wird.
- Ihre Anwendung sollte die Methode
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 IhrerConnection
-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:- Ihre Anwendung sollte die Methode
setConnectionProperties(int)
mit der KonstantePROPERTY_SELF_MANAGED
als Argument aufrufen, um anzugeben, dass die Verbindung von einer aufrufenden Anwendung stammt. - Wenn Ihre Anwendung das Halten von Aufrufen unterstützt, rufen Sie die Methode
setConnectionCapabilities(int)
auf und legen Sie das Argument auf den Bitmaskenwert der KonstantenCAPABILITY_HOLD
undCAPABILITY_SUPPORT_HOLD
fest. - Verwenden Sie zum Festlegen des Namens des Aufrufs die Methode
setCallerDisplayName(String, int)
und übergeben Sie diePRESENTATION_ALLOWED
-Konstante alsint
-Parameter, um anzugeben, dass der Name des Aufrufers angezeigt werden soll. - Verwenden Sie die Methode
setAddress(Uri, int)
des ObjektsConnection
, um die Telefonnummer oder Adresse des eingehenden Anrufs anzugeben. - Damit der ausgehende Aufruf den richtigen Videostatus hat, rufen Sie die Methode
setVideoState(int)
desConnection
-Objekts auf und senden Sie den Wert, der von dergetVideoState()
-Methode desConnectionRequest
-Objekts zurückgegeben wird.
- Ihre Anwendung sollte die Methode
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 unterInCallService
.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 unterInCallService
.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 unteronAnswer(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 undREJECTED
als Parameter angegeben werden. Ihre App sollte dann die Methodedestroy()
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 undLOCAL
als Parameter angeben, um anzugeben, dass die Verbindung des Aufrufs aufgrund einer Nutzeranfrage getrennt wurde. Ihre App sollte dann die Methodedestroy()
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 unterInCallService
.
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:
- Ihre App empfängt neue eingehende Anrufe mit den üblichen Methoden.
- Mit der Methode
addNewIncomingCall(PhoneAccountHandle, Bundle)
informieren Sie das Telekommunikationssubsystem über den neuen eingehenden Anruf. - Das Telekommunikationssubsystem bindet sich an die Implementierung
ConnectionService
Ihrer Anwendung und fordert mit der MethodeonCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)
eine neue Instanz der KlasseConnection
an, die den neuen eingehenden Aufruf darstellt. - Das Telekommunikationssubsystem teilt der Anwendung mit, dass die Benutzeroberfläche für eingehende Anrufe mithilfe der Methode
onShowIncomingCallUi()
angezeigt werden soll. - Ihre App zeigt die eingehende UI über eine Benachrichtigung mit einem verknüpften Full-Screen-Intent an. Weitere Informationen findest du unter
onShowIncomingCallUi()
. - Rufen Sie die Methode
setActive()
auf, wenn der Nutzer den eingehenden Anruf annimmt, oder rufen Sie die MethodesetDisconnected(DisconnectCause)
auf, indem SieREJECTED
als Parameter angeben, gefolgt von einem Aufruf der Methodedestroy()
, 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:
- Ihre App empfängt neue eingehende Anrufe mit den üblichen Methoden.
- Mit der Methode
addNewIncomingCall(PhoneAccountHandle, Bundle)
informieren Sie das Telekommunikationssubsystem über den neuen eingehenden Anruf. - Das Telekommunikationssubsystem bindet sich an die
ConnectionService
-Implementierung Ihrer Anwendung und fordert mit der MethodeonCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)
eine neue Instanz desConnection
-Objekts an, das den neuen eingehenden Aufruf darstellt. - Das Telekommunikationssubsystem zeigt die Benutzeroberfläche für eingehende Anrufe für Ihren eingehenden Anruf an.
- Wenn der Nutzer den Aufruf annimmt, ruft das Telekommunikationssubsystem die Methode
onAnswer()
auf. Sie sollten die MethodesetActive()
aufrufen, um dem Telekommunikationssubsystem zu signalisieren, dass der Aufruf jetzt verbunden ist. - Wenn der Nutzer den Aufruf ablehnt, ruft das Telekommunikationssubsystem die Methode
onReject()
auf. Sie sollten die MethodesetDisconnected(DisconnectCause)
aufrufen undREJECTED
als Parameter angeben, gefolgt von einem Aufruf der Methodedestroy()
.
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:
- Der Nutzer initiiert einen ausgehenden Anruf in Ihrer App.
- 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-Schematel:
. - Mit dem Parameter
Bundle
können Sie Informationen zu Ihrer aufrufenden App angeben. Dazu fügen Sie dasPhoneAccountHandle
-Objekt Ihrer App zumEXTRA_PHONE_ACCOUNT_HANDLE
-Extra hinzu. Ihre App muss bei jedem ausgehenden Anruf das ObjektPhoneAccountHandle
bereitstellen. - Mit dem Parameter
Bundle
können Sie auch angeben, ob der ausgehende Anruf Video umfasst. Dazu geben Sie den WertSTATE_BIDIRECTIONAL
im zusätzlichenEXTRA_START_CALL_WITH_VIDEO_STATE
an. Beachten Sie, dass das Telekommunikationssubsystem Videoanrufe standardmäßig an die Freisprechfunktion weiterleitet.
- Der Parameter
- Das Telekommunikationssubsystem bindet sich an die
ConnectionService
-Implementierung Ihrer Anwendung. - 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. - Wenn Ihre Anwendung den ausgehenden Aufruf ausführen kann, ruft das Telekommunikationssubsystem die Methode
onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)
auf. Die App sollte eine Instanz derConnection
-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. - 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:
- Rufen Sie das
setDisconnected(DisconnectCause)
auf, dasLOCAL
als Parameter sendet, wenn der Nutzer den Aufruf beendet hat, oderREMOTE
als Parameter, wenn die andere Partei den Aufruf beendet hat. - 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
undCAPABILITY_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:
- Berechtigung „MANAGE_ONGOING_CALLS“ in Ihrem Manifest deklarieren
- 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 - Diesen InCallService mit der Berechtigung BIND_INCALL_SERVICE implementieren
Benachrichtigung über eingehenden Anruf anzeigen
Wenn die Anwendung einen neuen eingehenden Anruf überInCallService#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());
```