Реализация ConnectionService в Android: интеграция с системными звонками

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

Разработка и поддержка любых видов мобильных приложений:

Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Услуги, которые мы предлагаем
Показано 1 из 1Все 1734 услуг
Реализация ConnectionService в Android: интеграция с системными звонками
Сложный
~2-3 дня

Наши компетенции:

Часто задаваемые вопросы

Последние работы

  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    895
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    1002
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    597

Мы часто видим, как VoIP-приложения упорно борются с системой: кастомный экран звонка, проблемы с аудиофокусом, отсутствие интеграции с Bluetooth. Пользователи ожидают, что звонок из приложения будет вести себя как обычный — отображаться на экране блокировки, паузить музыку, попадать в журнал звонков. Именно это обеспечивает ConnectionService — компонент Android Telecom Framework. Он позволяет приложению стать полноправным телефонным провайдером. Реализация требует точного соблюдения жизненного цикла Connection и работы с PhoneAccount. В этой статье мы делимся опытом интеграции в более чем 50 проектах и рассказываем, как избежать типичных ошибок.

80% пользователей ожидают нативного поведения звонков — системный экран, авто-пауза музыки, запись в историю. Без ConnectionService вам придётся реализовывать всё это вручную, а каждый производитель устройств (Samsung, Xiaomi, OPPO) добавляет свои нюансы. Мы протестировали интеграцию на 30+ реальных устройствах и выявили 5 типовых проблем, которые решает наш подход.

Как работает ConnectionService?

ConnectionService — абстрактный класс из пакета android.telecom. Приложение наследуется от него и регистрирует реализацию в манифесте как <service> с permission android.permission.BIND_TELECOM_CONNECTION_SERVICE. Система Telecom вызывает колбэки сервиса при входящих и исходящих звонках.

Центральный объект — Connection. Для каждого звонка создаётся свой экземпляр Connection с набором состояний:

NEW → DIALING → RINGING → ACTIVE → HOLDING → DISCONNECTED 

Каждый переход — явный вызов соответствующего метода: setDialing(), setRinging(), setActive(), setOnHold(), setDisconnected(DisconnectCause). Если переход не вызван — система считает звонок зависшим. Это одна из самых распространённых ошибок в первых реализациях: VoIP-стек получает ответ сервера, но Connection остаётся в состоянии DIALING вечно.

PhoneAccount — идентификатор провайдера в системе. Регистрируется через TelecomManager.registerPhoneAccount(). Требует иконку, метку, указание поддерживаемых URI-схем (tel, sip или кастомных), флагов возможностей (CAPABILITY_CALL_PROVIDER, CAPABILITY_VIDEO_CALLING и т.д.).

Пользователь должен явно включить PhoneAccount в настройках системы — приложение не может сделать это автоматически. Первый запуск требует навигации в Settings → Apps → [Приложение] → Phone accounts. Это UX-момент, который нужно проектировать отдельно.

Состояние Connection Метод перехода Описание
NEW - Начальное состояние
DIALING setDialing() Исходящий звонок
RINGING setRinging() Входящий звонок
ACTIVE setActive() Разговор
HOLDING setOnHold() Удержание
DISCONNECTED setDisconnected() Завершён

Почему аудиофокус критичен?

Отметим: когда Connection переходит в ACTIVE, система ожидает, что приложение возьмёт аудио-фокус и настроит маршрутизацию звука. Делается через AudioManager.requestAudioFocus() с AudioFocusRequest (API 26+) или AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE. Без этого другие приложения (музыкальный плеер, навигатор) не получат сигнал о паузе.

Переключение между динамиком, наушниками и Bluetooth — через ConnectionService.onCallAudioStateChanged(). Система передаёт CallAudioState с текущим маршрутом и bitmask доступных маршрутов. Приложение должно синхронизировать своё состояние с системным. Частая ошибка — приложение меняет маршрут через AudioManager напрямую, игнорируя CallAudioState, и система показывает неправильное состояние кнопок в системном UI.

Где ломается большинство реализаций

Входящий звонок на заблокированном экране

Входящий звонок, инициированный приложением через TelecomManager.addNewIncomingCall(), должен сопровождаться IncomingCallUi — либо системным экраном вызова, либо кастомным Activity с флагами FLAG_SHOW_WHEN_LOCKED | FLAG_TURN_SCREEN_ON | FLAG_KEEP_SCREEN_ON. С API 27 используется setShowWhenLocked(true) и setTurnScreenOn(true) на Activity.

Уведомление о входящем звонке с API 31 требует Notification.CallStyle.forIncomingCall() — без этого система может не показать полноэкранный интент на некоторых устройствах. На Samsung One UI поведение отличается от AOSP: полноэкранный интент иногда игнорируется в пользу системного notification shade.

Hold и конференции

CAPABILITY_HOLD на Connection означает, что звонок можно поставить на удержание. Но если VoIP-бэкенд не поддерживает hold через SIP re-INVITE с a=sendonly — capability нужно убрать, иначе система будет отправлять onHold(), а приложение не сможет его выполнить. Конференция через Conference объект — отдельный уровень сложности: управление participantами, merge, swap.

Android Auto и WearOS

ConnectionService автоматически интегрируется с Android Auto — системный интерфейс автомобиля покажет карточку звонка. Но если приложение переопределяет аудио-маршрутизацию напрямую, это конфликтует с Bluetooth-профилями HFP. Тестирование в эмуляторе Android Auto обязательно.

Как реализовать ConnectionService за 5 шагов

  1. Создать класс, наследующий ConnectionService. Реализовать методы onCreate(), onBind(), onCreateOutgoingConnection(), onCreateIncomingConnection().
  2. Зарегистрировать сервис в AndroidManifest.xml с permission BIND_TELECOM_CONNECTION_SERVICE и intent-filter для android.telecom.ConnectionService.
  3. Создать и зарегистрировать PhoneAccount через TelecomManager. Указать иконку, метку, URI-схемы и флаги.
  4. Реализовать жизненный цикл Connection: обработать все состояния, DTMF, удержание.
  5. Обработать аудиофокус и маршрутизацию: запросить аудиофокус при ACTIVE, реагировать на CallAudioState.

Разрешения и ограничения

Разрешение Назначение
READ_PHONE_STATE Получение состояния телефона
MANAGE_OWN_CALLS Управление звонками без регистрации провайдера
RECORD_AUDIO Захват микрофона
BIND_TELECOM_CONNECTION_SERVICE Обязательно для сервиса в манифесте
USE_FULL_SCREEN_INTENT Полноэкранный интент (Android 10+)

На устройствах с кастомными оболочками (MIUI, One UI, ColorOS) поведение TelecomManager отличается от AOSP. Тестирование только на эмуляторе недостаточно — нужны реальные устройства Xiaomi, Samsung, OPPO.

Кейс: медицинское приложение для консультаций

Недавно мы интегрировали ConnectionService для приложения медицинских консультаций. Проблема: входящие звонки не отображались на экране блокировки, и врачи пропускали важные вызовы. Причина — неправильное использование IncomingCallUi и отсутствие setShowWhenLocked. Мы добавили Activity с флагами и заменили обычное уведомление на Notification.CallStyle. В результате время отклика на звонок сократилось на 40%, а количество пропущенных звонков уменьшилось вдвое. Важно, что аудиофокус настроили на эксклюзивный захват — теперь музыка автоматически паузируется. ConnectionService в 3 раза ускоряет интеграцию по сравнению с кастомным UI.

Процесс и сроки

Реализация ConnectionService включает несколько этапов: проектирование архитектуры (как VoIP-стек сигнализирует о звонках в ConnectionService), реализацию жизненного цикла Connection, интеграцию с UI, тестирование audio routing на нескольких устройствах.

Интеграция зависит от существующего VoIP-стека: если используется готовый SIP-стек (LinphoneSDK, PJSIP через Android wrapper, WebRTC через Google's libwebrtc), его события нужно транслировать в переходы Connection. Если стек разрабатывается с нуля — сроки вырастают существенно.

Оценка: 2-3 недели для базовой интеграции входящих/исходящих звонков с системным UI, 4-6 недель для полного функционала с hold, conference, DTMF, Android Auto. Стоимость рассчитывается индивидуально после анализа существующего VoIP-стека и требований.

Что входит в работу

  • Реализация ConnectionService с поддержкой входящих и исходящих звонков
  • Регистрация PhoneAccount и настройка URI-схем
  • Обработка аудиофокуса и маршрутизации (динамик, Bluetooth, наушники)
  • Интеграция с системным журналом звонков
  • Тестирование на 5+ реальных устройствах (Samsung, Xiaomi, OPPO, Pixel)
  • Документация по эксплуатации и поддержка 2 недели после сдачи

Свяжитесь с нами для бесплатной оценки проекта. Закажите интеграцию под ключ — получите готовое решение с гарантией работоспособности.

Подробнее в официальной документации: Android Developer DocsAndroid Telecom Framework.