Das Android Telecom-Framework (auch einfach als „Telecom“ bezeichnet) verwaltet Audio- und Videoanrufe auf einem Android-Gerät. Dazu gehören SIM-basierte Anrufe, z. B. Anrufe, die das Telefonie-Framework verwenden, und VoIP-Aufrufe, bei denen die ConnectionService
API implementiert ist.
Die Hauptkomponenten, die von Telecom verwaltet werden, sind ConnectionService
und InCallService
.
Eine ConnectionService
-Implementierung verwendet Technologien wie VoIP, um Anrufe mit anderen Parteien zu verbinden. Die gängigste ConnectionService
-Implementierung auf einem Telefon ist die Telefonie-ConnectionService
. Es stellt Anrufe über Mobilfunkanbieter her.
Eine InCallService
-Implementierung bietet eine Benutzeroberfläche für von der Telekommunikationsbranche verwaltete Anrufe und ermöglicht dem Nutzer, diese Aufrufe zu steuern und mit ihnen zu interagieren. Die gängigste Implementierung einer InCallService
ist die in einem Gerät enthaltene Telefon-App.
Telekommunikation fungiert als Telefonzentrale. Sie leitet Aufrufe von ConnectionService
-Implementierungen an die aufrufenden Benutzeroberflächen von InCallService
-Implementierungen weiter.
Die Implementierung der Telecom APIs kann aus folgenden Gründen sinnvoll sein:
- Um einen Ersatz für die Systemtelefon-App zu erstellen.
- Um eine Anruflösung in die Android-Telefonie zu integrieren.
Ersatz-Telefon-App erstellen
Wenn du einen Ersatz für die Standard-Telefon-App auf einem Android-Gerät erstellen möchtest, implementiere die InCallService
API. 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 Aufrufe verarbeiten, die dem Telekommunikations-Framework bekannt sind, und es darf keine Annahmen über die Art der Aufrufe getroffen werden. Es darf beispielsweise nicht davon ausgegangen werden, dass Anrufe SIM-basierte Telefonieanrufe sind, und es darf keine Anrufbeschränkungen implementiert werden, die auf einer
ConnectionService
basieren, wie die Erzwingung von Telefonieeinschränkungen für Videoanrufe.
Weitere Informationen findest du unter InCallService
.
Anruflösung einbinden
Sie haben folgende Möglichkeiten, Ihre Anruflösung in Android zu integrieren:
Selbstverwaltete ConnectionService API implementieren:Diese Option ist ideal für Entwickler von eigenständigen Anruf-Apps, die ihre Anrufe weder in der standardmäßigen Telefon-App noch andere Anrufe auf der Benutzeroberfläche anzeigen möchten.
Wenn Sie eine selbstverwaltete
ConnectionService
verwenden, unterstützt die Anwendung nicht nur die Interaktion mit nativen Telefonieaufrufen auf dem Gerät, sondern auch mit anderen eigenständigen Anrufanwendungen, die diese API implementieren. Über die selbstverwalteteConnectionService
API werden auch das Audiorouting und der Fokus verwaltet. Weitere Informationen finden Sie unter Anruf-App erstellen.Managed ConnectionService API implementieren:Diese Option erleichtert die Entwicklung einer Anruflösung, die die Benutzeroberfläche für Anrufe über die vorhandene Telefonanwendung auf dem Gerät bereitstellt. Beispiele hierfür sind Implementierungen von SIP-Anruf- und VoIP-Anrufdiensten von Drittanbietern. Weitere Informationen findest du unter
getDefaultDialerPackage()
.Ein
ConnectionService
allein ermöglicht nur die Verbindung von Anrufen. Sie hat keine zugehörige Benutzeroberfläche.Implementiere sowohl die InCallService API als auch die ConnectionService API: Diese Option ist ideal, wenn du deine eigene
ConnectionService
-basierte Anruflösung mit eigener Benutzeroberfläche erstellen und auch alle anderen Android-Aufrufe in derselben Benutzeroberfläche anzeigen möchtest. Bei diesem Ansatz darf die Implementierung vonInCallService
keine Annahmen über die Quellen der angezeigten Aufrufe treffen. Außerdem muss die Implementierung vonConnectionService
auch dann funktionieren, wenn die Standard-Telefon-App nicht auf den benutzerdefiniertenInCallService
festgelegt ist.
Anruf-Filter
Auf Geräten mit Android 10 (API-Level 29) oder höher kann deine App Anrufe von Nummern, die nicht im Adressbuch des Nutzers enthalten sind, als potenzielle Spamanrufe erkennen. Nutzer können Spamanrufe automatisch ablehnen lassen. Um Nutzern mehr Transparenz zu bieten, wenn Anrufe verpasst werden, werden Informationen zu diesen blockierten Anrufen in der Anrufliste gespeichert. Wenn du die Android 10 API verwendest, musst du nicht die Berechtigung READ_CALL_LOG
vom Nutzer einholen, um Funktionen für den Anruf-Filter und die Anrufer-ID nutzen zu können.
Sie verwenden eine CallScreeningService
-Implementierung, um Aufrufe zu filtern. Rufen Sie die Funktion onScreenCall()
für alle neuen eingehenden oder ausgehenden Anrufe auf, wenn sich die Nummer nicht in der Kontaktliste des Nutzers befindet. Informationen zum Aufruf findest du im Objekt Call.Details
. Konkret enthält die Funktion getCallerNumberVerificationStatus()
vom Netzwerkanbieter Informationen zu der anderen Nummer.
Wenn der Bestätigungsstatus fehlgeschlagen ist, weist dies darauf hin, dass der Anruf von einer ungültigen Nummer oder einem potenziellen Spamanruf stammt.
Kotlin
class ScreeningService : CallScreeningService() { // This function is called when an ingoing or outgoing call // is from a number not in the user's contacts list override fun onScreenCall(callDetails: Call.Details) { // Can check the direction of the call val isIncoming = callDetails.callDirection == Call.Details.DIRECTION_INCOMING if (isIncoming) { // the handle (e.g. phone number) that the Call is currently connected to val handle: Uri = callDetails.handle // determine if you want to allow or reject the call when (callDetails.callerNumberVerificationStatus) { Connection.VERIFICATION_STATUS_FAILED -> { // Network verification failed, likely an invalid/spam call. } Connection.VERIFICATION_STATUS_PASSED -> { // Network verification passed, likely a valid call. } else -> { // Network could not perform verification. // This branch matches Connection.VERIFICATION_STATUS_NOT_VERIFIED. } } } } }
Java
class ScreeningService extends CallScreeningService { @Override public void onScreenCall(@NonNull Call.Details callDetails) { boolean isIncoming = callDetails.getCallDirection() == Call.Details.DIRECTION_INCOMING; if (isIncoming) { Uri handle = callDetails.getHandle(); switch (callDetails.getCallerNumberVerificationStatus()) { case Connection.VERIFICATION_STATUS_FAILED: // Network verification failed, likely an invalid/spam call. break; case Connection.VERIFICATION_STATUS_PASSED: // Network verification passed, likely a valid call. break; default: // Network could not perform verification. // This branch matches Connection.VERIFICATION_STATUS_NOT_VERIFIED } } } }
Legen Sie die onScreenCall()
-Funktion so fest, dass respondToCall()
aufgerufen wird, um dem System mitzuteilen, wie der neue Aufruf beantwortet werden soll. Diese Funktion verwendet einen CallResponse
-Parameter, mit dem Sie das System anweisen können, den Aufruf zu blockieren, ihn so abzulehnen, als er ihn der Nutzer tat, oder ihn stummzuschalten. Sie können das System auch anweisen, diesen Aufruf gar nicht zur Anrufliste des Geräts hinzuzufügen.
Kotlin
// Tell the system how to respond to the incoming call // and if it should notify the user of the call. val response = CallResponse.Builder() // Sets whether the incoming call should be blocked. .setDisallowCall(false) // Sets whether the incoming call should be rejected as if the user did so manually. .setRejectCall(false) // Sets whether ringing should be silenced for the incoming call. .setSilenceCall(false) // Sets whether the incoming call should not be displayed in the call log. .setSkipCallLog(false) // Sets whether a missed call notification should not be shown for the incoming call. .setSkipNotification(false) .build() // Call this function to provide your screening response. respondToCall(callDetails, response)
Java
// Tell the system how to respond to the incoming call // and if it should notify the user of the call. CallResponse.Builder response = new CallResponse.Builder(); // Sets whether the incoming call should be blocked. response.setDisallowCall(false); // Sets whether the incoming call should be rejected as if the user did so manually. response.setRejectCall(false); // Sets whether ringing should be silenced for the incoming call. response.setSilenceCall(false); // Sets whether the incoming call should not be displayed in the call log. response.setSkipCallLog(false); // Sets whether a missed call notification should not be shown for the incoming call. response.setSkipNotification(false); // Call this function to provide your screening response. respondToCall(callDetails, response.build());
Du musst die CallScreeningService
-Implementierung in der Manifestdatei mit dem entsprechenden Intent-Filter und der entsprechenden Berechtigung registrieren, damit das System sie korrekt auslösen kann.
<service
android:name=".ScreeningService"
android:permission="android.permission.BIND_SCREENING_SERVICE">
<intent-filter>
<action android:name="android.telecom.CallScreeningService" />
</intent-filter>
</service>
Anrufe weiterleiten
Geräte mit Android 10 oder höher verwalten Anruf-Intents anders als Geräte mit Android 9 oder niedriger. Unter Android 10 und höher wurde die ACTION_NEW_OUTGOING_CALL
-Übertragung eingestellt und durch die CallRedirectionService
API ersetzt. CallRedirectionService
stellt Schnittstellen bereit, mit denen Sie ausgehende Aufrufe der Android-Plattform ändern können. Drittanbieter-Apps können beispielsweise Anrufe abbrechen und über VoIP umleiten.
Kotlin
class RedirectionService : CallRedirectionService() { override fun onPlaceCall( handle: Uri, initialPhoneAccount: PhoneAccountHandle, allowInteractiveResponse: Boolean ) { // Determine if the call should proceed, be redirected, or cancelled. val callShouldProceed = true val callShouldRedirect = false when { callShouldProceed -> { placeCallUnmodified() } callShouldRedirect -> { // Update the URI to point to a different phone number or modify the // PhoneAccountHandle and redirect. redirectCall(handle, initialPhoneAccount, true) } else -> { cancelCall() } } } }
Java
class RedirectionService extends CallRedirectionService { @Override public void onPlaceCall( @NonNull Uri handle, @NonNull PhoneAccountHandle initialPhoneAccount, boolean allowInteractiveResponse ) { // Determine if the call should proceed, be redirected, or cancelled. // Your app should implement this logic to determine the redirection. boolean callShouldProceed = true; boolean callShouldRedirect = false; if (callShouldProceed) { placeCallUnmodified(); } else if (callShouldRedirect) { // Update the URI to point to a different phone number or modify the // PhoneAccountHandle and redirect. redirectCall(handle, initialPhoneAccount, true); } else { cancelCall(); } } }
Sie müssen diesen Dienst im Manifest registrieren, damit das System ihn ordnungsgemäß starten kann.
<service
android:name=".RedirectionService"
android:permission="android.permission.BIND_CALL_REDIRECTION_SERVICE">
<intent-filter>
<action android:name="android.telecom.CallRedirectionService"/>
</intent-filter>
</service>
Damit Sie einen Weiterleitungsdienst verwenden können, muss Ihre App die Rolle für die Anrufweiterleitung von RoleManager
anfordern. Dadurch wird der Nutzer gefragt, ob er zulassen möchte, dass Ihre App Anrufweiterleitungen verarbeitet. Wenn Ihrer Anwendung diese Rolle nicht gewährt wird, wird der Weiterleitungsdienst nicht verwendet.
Sie sollten prüfen, ob Ihre Anwendung diese Rolle hat, wenn der Nutzer sie startet, damit Sie sie bei Bedarf anfordern können. Sie starten einen Intent, der von RoleManager
erstellt wurde. Überschreiben Sie daher die Funktion onActivityResult()
, um die Auswahl des Nutzers zu verarbeiten.
Kotlin
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Tell the system that you want your app to handle call redirects. This // is done by using the RoleManager to register your app to handle redirects. if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) { val roleManager = getSystemService(Context.ROLE_SERVICE) as RoleManager // Check if the app needs to register call redirection role. val shouldRequestRole = roleManager.isRoleAvailable(RoleManager.ROLE_CALL_REDIRECTION) && !roleManager.isRoleHeld(RoleManager.ROLE_CALL_REDIRECTION) if (shouldRequestRole) { val intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_CALL_REDIRECTION) startActivityForResult(intent, REDIRECT_ROLE_REQUEST_CODE) } } } companion object { private const val REDIRECT_ROLE_REQUEST_CODE = 1 } }
Java
class MainActivity extends AppCompatActivity { private static final int REDIRECT_ROLE_REQUEST_CODE = 0; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Tell the system that you want your app to handle call redirects. This // is done by using the RoleManager to register your app to handle redirects. if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) { RoleManager roleManager = (RoleManager) getSystemService(Context.ROLE_SERVICE); // Check if the app needs to register call redirection role. boolean shouldRequestRole = roleManager.isRoleAvailable(RoleManager.ROLE_CALL_REDIRECTION) && !roleManager.isRoleHeld(RoleManager.ROLE_CALL_REDIRECTION); if (shouldRequestRole) { Intent intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_CALL_REDIRECTION); startActivityForResult(intent, REDIRECT_ROLE_REQUEST_CODE); } } } }