Panoramica del framework per le telecomunicazioni

Il framework Android Telecom (noto anche semplicemente come "Telecom") gestisce audio e per le videochiamate su un dispositivo Android. Sono incluse le chiamate basate su SIM, ad esempio chiamate che utilizzano il framework di telefonia e le chiamate VoIP che implementano API ConnectionService.

I componenti principali gestiti da Telecom sono ConnectionService e InCallService

Un'implementazione di ConnectionService usa tecnologie come il VoIP per connettersi chiamate ad altri soggetti. L'implementazione di ConnectionService più comune su un telefono è la telefonia ConnectionService. Connette le chiamate dell'operatore.

Un'implementazione di InCallService fornisce un'interfaccia utente per le chiamate gestite Telecom e consente all'utente di controllare e interagire con queste chiamate. Il più un'implementazione comune di InCallService è l'app per smartphone abbinata a un dispositivo.

Le telecomunicazioni fanno da centralino. Instrada le chiamate che ConnectionService le implementazioni forniscono alle interfacce utente di chiamata che InCallService le implementazioni.

Ti consigliamo di implementare le API Telecom per i seguenti motivi:

Crea un'app sostitutiva per lo smartphone

Per creare una sostituzione per l'app per smartphone predefinita su un dispositivo Android: implementare l'API InCallService. La tua implementazione deve soddisfare i seguenti requisiti requisiti:

  • Non deve avere funzionalità per le chiamate e deve essere esclusivamente dell'utente l'interfaccia utente per le chiamate.
  • Deve gestire tutte le chiamate di cui il framework Telecom è a conoscenza e non deve ipotesi sulla natura delle chiamate. Ad esempio, non deve presupporre le chiamate sono chiamate di telefonia basate su SIM e non implementano limitazioni delle chiamate che si basano su un valore ConnectionService qualsiasi, ad esempio l'applicazione forzata della telefonia restrizioni per le videochiamate.

Per ulteriori informazioni, vedi InCallService

Integra una soluzione per le chiamate

Per integrare la tua soluzione per le chiamate in Android, devi disporre le seguenti opzioni:

  • Implementa l'API ConnectionService autogestita: Questa opzione è ideale per gli sviluppatori di app per le chiamate autonome che non vogliono per mostrare le loro chiamate nell'app Telefono predefinita, né altre chiamate nell'interfaccia utente.

    Se utilizzi un ConnectionService autogestito, aiuti la tua app a interagiscono non solo con le chiamate di telefonia native sul dispositivo, ma anche con altre app di chiamata autonome che implementano questa API. Il modello autogestito L'API ConnectionService gestisce anche il routing e lo stato attivo dell'audio. Per maggiori dettagli, vedi Crea un'app per le chiamate.

  • Implementa l'API ConnectionService gestita: Questa opzione facilita lo sviluppo di una soluzione di chiamata che si basa sulle esistente per fornire l'interfaccia utente per le chiamate. Gli esempi includono un'implementazione di terze parti delle chiamate SIP e VoIP i servizi di machine learning. Per ulteriori dettagli, vedi getDefaultDialerPackage()

    Un ConnectionService da solo fornisce solo il mezzo per connettere le chiamate. it non ha un'interfaccia utente associata.

  • Implementa sia l'API InCallService che l'API ConnectionService: Questa opzione è ideale se vuoi creare modelli Soluzione di chiamata basata su ConnectionService, completa di un proprio utente e mostra tutte le altre chiamate Android nella stessa interfaccia utente. Quando utilizzi questo approccio, l'implementazione di InCallService non deve fare ipotesi sulle sorgenti delle chiamate che mostra. Inoltre, l'implementazione di ConnectionService deve continuare a funzionare senza app per smartphone predefinita impostata sul tuo InCallService personalizzato.

Filtro delle chiamate

I dispositivi con Android 10 (livello API 29) o versioni successive consentono alla tua app di identificare Chiamate da numeri non presenti nella rubrica dell'utente come potenziale spam chiamate. Gli utenti possono scegliere di rifiutare automaticamente le chiamate indesiderate. Per offrire una maggiore trasparenza per gli utenti quando perdono le chiamate, le informazioni vengono registrate nel registro chiamate. L'utilizzo dell'API Android 10 elimina requisito di ottenere READ_CALL_LOG autorizzazione da parte dell'utente per fornire il filtro delle chiamate e l'ID chiamante funzionalità.

Utilizzi un CallScreeningService per filtrare le chiamate. Chiama il onScreenCall() per qualsiasi nuova chiamata in arrivo o in uscita quando il numero non è nella elenco contatti dell'utente. Puoi controllare Call.Details oggetto per le informazioni in merito alla chiamata. In particolare, getCallerNumberVerificationStatus() include informazioni del provider di rete sull'altro numero. Se lo stato della verifica non è andato a buon fine, significa che la chiamata è da un numero non valido o 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() da chiamare respondToCall() per indicare al sistema come rispondere alla nuova chiamata. Questa funzione prende un CallResponse parametro che puoi utilizzare per indicare al sistema di bloccare la chiamata, rifiutarla come se l'utente lo ha fatto o silenziarlo. Puoi anche indicare al sistema di saltare l'aggiunta tutte le chiamate 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 di CallScreeningService nel file manifest con il filtro per intent e l'autorizzazione appropriati in modo che il sistema possa attivare in modo corretto.

<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 Dispositivi con Android 9 o versioni precedenti. Su Android 10 e versioni successive, ACTION_NEW_OUTGOING_CALL la trasmissione è deprecata e sostituita con CallRedirectionService tramite Google Cloud CLI o tramite l'API Compute Engine. CallRedirectionService fornisce interfacce che puoi utilizzare per modificare le chiamate in uscita effettuate dalla piattaforma Android. Ad esempio, terze parti le app 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 file manifest in modo che il sistema possa avviarlo in modo corretto.

<service
    android:name=".RedirectionService"
    android:permission="android.permission.BIND_CALL_REDIRECTION_SERVICE">
    <intent-filter>
        <action android:name="android.telecom.CallRedirectionService"/>
    </intent-filter>
</service>

Per usare un servizio di reindirizzamento, la tua app deve richiedere il ruolo Reindirizzamento chiamate da RoleManager. Verrà richiesto se vuole consentire all'app di gestire i reindirizzamenti delle chiamate. Se la tua app non disponi di questo ruolo, il tuo servizio di reindirizzamento non è utilizzato.

Devi controllare se la tua app ha questo ruolo quando l'utente avvia l'app, in modo da puoi richiederlo in base alle tue esigenze. Lanci un intent creato da RoleManager quindi assicurati di sostituire 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);
            }
        }
    }
}