Единая история звонков

Приложения VoIP могут интегрировать свои звонки в системный журнал вызовов. Это позволяет пользователям централизованно просматривать историю своих VoIP-звонков в системном приложении для набора номера и перезванивать непосредственно из этого приложения. В этом руководстве описаны необходимые изменения в приложениях для VoIP-звонков , системных приложениях для набора номера и в настройках управления унифицированной историей звонков .

Изменения в приложении для звонков

Для интеграции вашего VoIP-приложения с системным журналом вызовов выполните следующие действия.

Зарегистрировать фильтр намерения обратного вызова

Зарегистрируйте защищенный системой интент TelecomManager.ACTION_CALL_BACK .

После того, как этот фильтр намерений будет должным образом зарегистрирован, любые вызовы, добавленные вашим приложением с помощью CallsManager.addCall или других связанных API телекоммуникаций, будут автоматически регистрироваться системой. Система использует это зарегистрированное намерение для последующей отправки обратного вызова вашему приложению, когда пользователь выбирает запись в журнале VoIP-звонков в номеронабирателе, чтобы перезвонить.

<!-- Activity to handle the callback intent from the system dialer -->
<activity
    android:name=".VoipCallActivity"
    android:exported="true">

    <!-- Register callback intent -->
    <intent-filter>
        <action android:name="android.telecom.action.CALL_BACK" />
    </intent-filter>
</activity>

Исключить регистрацию звонков

После регистрации обратного вызова все звонки регистрируются в системном дозвонщике. Чтобы исключить отдельные звонки, установите логическое значение isLogExcluded в true в классе CallAttributesCompat .

CallAttributesCompat(
    displayName = displayName,
    address = address,
    isLogExcluded = excludeCallLogging, // to exclude call from logging
    direction = if (isIncoming) {
        CallAttributesCompat.DIRECTION_INCOMING
    } else {
        CallAttributesCompat.DIRECTION_OUTGOING
    },
    callType = CallAttributesCompat.CALL_TYPE_AUDIO_CALL,
    callCapabilities = (
        CallAttributesCompat.SUPPORTS_SET_INACTIVE
            or CallAttributesCompat.SUPPORTS_STREAM
            or CallAttributesCompat.SUPPORTS_TRANSFER
        ),
)

Обработка обратных вызовов

Вызовы, добавленные через CallsManager.addCall , получают уникальный UUID через CallControlScope.getCallId .

// check the intent action for CALL_BACK
if (intent.action == TelecomManager.ACTION_CALL_BACK) {
    launchCall(
        // fetching stored call details for the UUID to initiate callback
        callDetails = getCallDetails(
            uuid = intent.getStringExtra(TelecomManager.EXTRA_UUID)
        )
    )
}

Проверьте записи в журнале звонков.

The system call log maintains a finite number of entries and eventually purges old call records. Because the app stores a mapping of UUID s to call details for callback handling, it should periodically check which UUID s are still present in the system call log. If a UUID is no longer in the system log, the user cannot initiate a callback for that call, and the app can safely remove the mapping from its local storage. This practice helps optimize storage.

Чтобы получить текущий список UUID , присвоенных приложению в системном журнале, используйте CallLog.Calls.CONTENT_VOIP_URI .

Изменения в приложении для набора номера

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

Отображение журналов VoIP-звонков в приложении для набора номера.

По умолчанию журналы вызовов VoIP-приложений не отображаются в приложении для набора номера. Чтобы отобразить встроенные журналы вызовов в приложении для набора номера, выполните следующие действия:

  • В Android 16.1 (уровень API 36.1) добавьте параметр запроса include_voip_calls к поставщику контента CallLog.Calls , чтобы отображать журналы VoIP-звонков:

    CallLog.Calls.CONTENT_URI.buildUpon()
        .appendQueryParameter("include_voip_calls", "true")
        .build()

  • В Android 17 (уровень API 37) и выше используйте следующий формализованный поставщик контента и ключ параметра:

Инициировать обратные вызовы из приложения для набора номера.

To initiate a callback from a dialer, use TelecomManager.placeCall . The platform uses the unique CallLog.Calls._ID of the call log entry to launch the correct VoIP app. This launch includes a TelecomManager.ACTION_CALL_BACK intent, which is a system-defined action for initiating a return call. This intent contains the call's UUID in intent extra TelecomManager.EXTRA_UUID , allowing the VoIP app to identify which specific call is being called back.

// Uri generated with unique ID of the call log entry to launch the respective VoIP app for callback
val address = ContentUris.withAppendedId(CallLog.Calls.CONTENT_URI, callId)

// extra information required to initiate callback
val extras = Bundle()

telecomManager.placeCall(address, extras)

Управление настройками единой истории звонков

Начиная с Android 17 (уровень API 37), пользователи могут просматривать и включать/выключать единую историю звонков для каждого приложения отдельно в системных настройках (обычно в разделе «Настройки» > «Учетные записи звонков» > «Встроенные журналы звонков » или непосредственно в своем приложении для набора номера по умолчанию). Как сторонние приложения для звонков, так и приложения для набора номера могут взаимодействовать с этими настройками.

Чтобы открыть настройки унифицированной истории вызовов, запустите действие с помощью интента TelecomManager.ACTION_CONFIGURE_CALL_LOG_INTEGRATION :

val intent = Intent(TelecomManager.ACTION_CONFIGURE_CALL_LOG_INTEGRATION)
startActivity(intent)

Когда пользователь отключает единую историю звонков для приложения в системных настройках, система немедленно и навсегда удаляет все существующие записи журнала звонков для этого приложения из собственного источника журнала звонков ( CallLog.Calls ). Будущие звонки, инициированные или принятые этим приложением, не будут записываться в системный номеронабиратель.

Отслеживайте изменения предпочтений.

Чтобы синхронизировать данные при включении или выключении пользователем единой истории звонков для вашего приложения в системных настройках или в номеронабирателе, зарегистрируйте широковещательный приемник для широковещательного намерения TelecomManager.ACTION_VOIP_CALL_LOG_PREFERENCE ( android.telecom.action.VOIP_CALL_LOG_PREFERENCE ):

val receiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        if (intent.action == TelecomManager.ACTION_VOIP_CALL_LOG_PREFERENCE) {
            // Status of the Unified Call History of the app
            val isEnabled = intent.getBooleanExtra(
                TelecomManager.EXTRA_VOIP_CALL_LOG_PREFERENCE_STATUS,
                true
            )
        }
    }
}

When the user flips the toggle, the platform broadcasts this intent to your app containing the updated boolean state in the TelecomManager.EXTRA_VOIP_CALL_LOG_PREFERENCE_STATUS extra. Instead of waiting for periodic verification against CallLog.Calls , your app can listen to this broadcast. When unified call history is disabled (in other words, set to false ), your app can update its internal state or perform cleanup such as clearing locally cached call mappings used for callback handling.