Экранные вызовы

Устройства под управлением Android 10 (уровень API 29) или выше позволяют вашему приложению идентифицировать звонки с номеров, которых нет в адресной книге пользователя, как потенциальные спам-вызовы. Пользователи могут выбрать автоматическое отклонение спам-вызовов. Чтобы обеспечить большую прозрачность для пользователей в случае пропуска вызовов, информация об этих заблокированных вызовах записывается в журнал вызовов. Использование API Android 10 устраняет необходимость получения разрешения READ_CALL_LOG от пользователя для обеспечения функции фильтрации вызовов и идентификации вызывающего абонента.

Вы используете реализацию CallScreeningService для проверки вызовов. Вызовите функцию onScreenCall() для любых новых входящих или исходящих вызовов, если номер отсутствует в списке контактов пользователя. Вы можете проверить объект Call.Details для получения информации о вызове. В частности, функция getCallerNumberVerificationStatus() включает информацию от поставщика сети о другом номере. Если статус проверки не пройден, это верный признак того, что звонок поступил с неверного номера или что это потенциальный спам-вызов.

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.
               
}
           
}
       
}
   
}
}
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
           
}
       
}
   
}
}

Настройте функцию onScreenCall() для вызова respondToCall() , чтобы сообщить системе, как реагировать на новый вызов. Эта функция принимает параметр CallResponse , который вы можете использовать, чтобы указать системе заблокировать вызов, отклонить его, как если бы это сделал пользователь, или отключить его. Вы также можете указать системе вообще не добавлять этот вызов в журнал вызовов устройства.

// 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)
// 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());

Вы должны зарегистрировать реализацию CallScreeningService в файле манифеста с соответствующим фильтром намерений и разрешением, чтобы система могла правильно активировать ее.

<service
   
android:name=".ScreeningService"
   
android:permission="android.permission.BIND_SCREENING_SERVICE">
   
<intent-filter>
       
<action android:name="android.telecom.CallScreeningService" />
   
</intent-filter>
</service>