Il framework Android Telecom (noto anche semplicemente come "Telecom") gestisce audio e videochiamate su un dispositivo Android. Sono incluse le chiamate basate su SIM, ad esempio le chiamate che utilizzano il framework di telefonia e le chiamate VoIP che implementano l'API ConnectionService
.
I componenti principali gestiti da Telecom sono ConnectionService
e
InCallService
.
Un'implementazione ConnectionService
utilizza tecnologie come il VoIP per connettere
le chiamate ad altri interlocutori. L'implementazione ConnectionService
più comune su un
telefono è la telefonia ConnectionService
. Consente di connettere le chiamate operatore.
Un'implementazione InCallService
fornisce un'interfaccia utente per le chiamate gestite da
Telecom e consente all'utente di controllarle e interagire con queste chiamate. L'implementazione più comune di InCallService
è l'app per telefono integrata in un dispositivo.
Le telecomunicazioni fungono da centralino. Instrada le chiamate fornite dalle implementazioni di ConnectionService
alle interfacce utente per le chiamate fornite dalle implementazioni di InCallService
.
Potresti voler implementare le API Telecom per i seguenti motivi:
- Per creare una sostituzione per l'app del telefono di sistema.
- Per integrare una soluzione per le chiamate nell'esperienza di chiamata Android.
Crea un'app per telefono sostitutiva
Per creare una sostituzione per l'app telefonica predefinita su un dispositivo Android, implementa l'API InCallService
. La tua implementazione deve soddisfare i seguenti requisiti:
- Non deve avere funzionalità di chiamata e deve essere costituito esclusivamente dall'interfaccia utente per le chiamate.
- Deve gestire tutte le chiamate di cui è a conoscenza il framework delle telecomunicazioni e non fare ipotesi sulla natura delle chiamate. Ad esempio, non deve presupporre che le chiamate siano chiamate di telefonia basate su SIM, né implementare limitazioni alle chiamate basate su un qualsiasi
ConnectionService
, come l'applicazione di restrizioni telefoniche per le videochiamate.
Per maggiori informazioni, consulta
InCallService
.
Integra una soluzione per le chiamate
Per integrare la tua soluzione di chiamata in Android, hai a disposizione le seguenti opzioni:
Implementa l'API ConnectionService autogestita: questa opzione è ideale per gli sviluppatori di app per le chiamate autonome che non vogliono mostrare le proprie chiamate nell'app per telefono predefinita o visualizzare altre chiamate nell'interfaccia utente.
Quando utilizzi un
ConnectionService
autogestito, aiuti la tua app a interoperare non solo con le chiamate di telefonia native sul dispositivo, ma anche con altre app di chiamata autonome che implementano questa API. L'APIConnectionService
autogestita gestisce anche il routing audio e il focus. Per maggiori dettagli, vedi Creare un'app per le chiamate.Implementa l'API ConnectionService gestita: questa opzione facilita lo sviluppo di una soluzione di chiamata che si basa sull'applicazione telefonica del dispositivo esistente per fornire l'interfaccia utente per le chiamate. Gli esempi includono un'implementazione di terze parti delle chiamate SIP e dei servizi di chiamata VoIP. Per maggiori dettagli, consulta
getDefaultDialerPackage()
.Un
ConnectionService
da solo fornisce solo il mezzo per collegare le chiamate. Non è associata a un'interfaccia utente.Implementa sia l'API InCallService che l'API ConnectionService: questa opzione è ideale se vuoi creare la tua soluzione di chiamata basata su
ConnectionService
, completa della sua interfaccia utente, nonché mostrare tutte le altre chiamate Android nella stessa interfaccia utente. Quando utilizzi questo approccio, l'implementazione diInCallService
non deve fare ipotesi sull'origine delle chiamate visualizzate. Inoltre, la tua implementazione diConnectionService
deve continuare a funzionare senza che l'app per telefono predefinita sia impostata sulla tuaInCallService
personalizzata.
Filtro delle chiamate
I dispositivi con Android 10 (livello API 29) o versioni successive consentono alla tua app di identificare come potenziali chiamate indesiderate le chiamate provenienti da numeri non presenti nella rubrica dell'utente. Gli utenti possono scegliere di rifiutare automaticamente le chiamate indesiderate. Per garantire una maggiore trasparenza agli utenti quando perdono chiamate, le informazioni su queste chiamate bloccate vengono registrate nel registro chiamate. L'utilizzo dell'API Android 10 elimina il
requisito di ottenere l'autorizzazione
READ_CALL_LOG
da parte dell'utente per fornire le funzionalità di filtro delle chiamate e ID chiamante.
Utilizzi un'implementazione di CallScreeningService
per filtrare le chiamate. Chiama la funzione onScreenCall()
per tutte le nuove chiamate in arrivo o in uscita quando il numero non è nell'elenco contatti dell'utente. Puoi controllare l'oggetto Call.Details
per informazioni sulla chiamata. In particolare, la funzione getCallerNumberVerificationStatus()
include informazioni del fornitore di rete relative all'altro numero.
Se lo stato della verifica non è riuscito, è un buon segnale che la chiamata proviene da un numero non valido o da una potenziale chiamata indesiderata.
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 } } } }
Imposta la funzione onScreenCall()
su respondToCall()
per indicare al sistema come rispondere alla nuova chiamata. Questa funzione utilizza un parametro CallResponse
che puoi utilizzare per indicare al sistema di bloccare la chiamata, rifiutarla come se l'utente lo avesse fatto o silenziarla. Puoi anche indicare al sistema di saltare l'aggiunta
di questa chiamata al registro chiamate del dispositivo.
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());
Devi registrare l'implementazione CallScreeningService
nel file manifest con l'autorizzazione e il filtro per intent appropriati in modo che il sistema possa attivarla correttamente.
<service
android:name=".ScreeningService"
android:permission="android.permission.BIND_SCREENING_SERVICE">
<intent-filter>
<action android:name="android.telecom.CallScreeningService" />
</intent-filter>
</service>
Reindirizzare una chiamata
I dispositivi con Android 10 o versioni successive gestiscono gli intent di chiamata in modo diverso rispetto ai dispositivi con Android 9 o versioni precedenti. Su Android 10 e versioni successive, la trasmissione di ACTION_NEW_OUTGOING_CALL
è deprecata e viene sostituita dall'API CallRedirectionService
. L'CallRedirectionService
fornisce interfacce che puoi utilizzare per
modificare le chiamate in uscita effettuate dalla piattaforma Android. Ad esempio, le app di terze parti potrebbero annullare le chiamate e reindirizzarle tramite VoIP.
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(); } } }
Devi registrare questo servizio nel manifest in modo che il sistema possa avviarlo correttamente.
<service
android:name=".RedirectionService"
android:permission="android.permission.BIND_CALL_REDIRECTION_SERVICE">
<intent-filter>
<action android:name="android.telecom.CallRedirectionService"/>
</intent-filter>
</service>
Per utilizzare un servizio di reindirizzamento, la tua app deve richiedere il ruolo di reindirizzamento chiamate da RoleManager
. Verrà chiesto all'utente se vuole consentire alla tua app di gestire i reindirizzamenti delle chiamate. Se all'app non viene concesso questo ruolo, il servizio di reindirizzamento non viene utilizzato.
Devi controllare se la tua app ha questo ruolo quando l'utente avvia l'app, in modo da poter richiedere questo ruolo in base alle esigenze. Lancia un intent creato da RoleManager
, quindi assicurati di sostituire la funzione onActivityResult()
per gestire la selezione dell'utente.
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); } } } }