Разработка голосовых звонков (VoIP) в мобильном приложении

TRUETECH занимается разработкой, поддержкой и обслуживанием мобильных приложений iOS, Android, PWA. Имеем большой опыт и экспертизу для публикации мобильных приложений в популярные маркеты Google Play, App Store, Amazon, AppGallery и другие.
Разработка и поддержка любых видов мобильных приложений:
Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

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

Предлагаемые услуги
Показано 1 из 1 услугВсе 1735 услуг
Разработка голосовых звонков (VoIP) в мобильном приложении
Сложная
от 1 недели до 3 месяцев
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1054
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    445

Разработка голосовых звонков (VoIP) в мобильном приложении

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

Архитектура VoIP-звонка

Голосовой звонок состоит из двух независимых потоков:

Сигнализация — управляющий канал: кто звонит, принять/отклонить, завершить. Передаётся через WebSocket, SIP или XMPP. Сигнальные сообщения малы (JSON несколько сотен байт), но требуют надёжной доставки.

Медиапоток — аудио между участниками. Передаётся через WebRTC (RTP поверх UDP) или проприетарные протоколы (Twilio, Vonage). UDP допускает потерю пакетов ради низкой задержки — это нормально для голоса. Задержка важнее, чем потеря 1–2% пакетов.

Самостоятельная реализация медиаслоя — WebRTC. Managed-решения — Twilio Voice, Vonage Voice, Agora. Разница в сложности, гибкости и стоимости.

iOS: CallKit — без него не обойтись

На iOS VoIP без CallKit технически возможен, но:

  • Приложение не получает аудиосессию при входящем звонке на заблокированном экране
  • Система не показывает системный экран входящего звонка (пользователи привыкли к нему)
  • После iOS 13 приложения без CallKit не получают PushKit уведомления для VoIP

CallKit — системный фреймворк для интеграции VOIP-звонков в интерфейс телефона. Показывает системный экран входящего звонка, управляет аудиосессией, поддерживает Bluetooth/AirPods, отображает звонки в истории вызовов.

import CallKit

class CallManager: NSObject {
    let provider: CXProvider
    let callController = CXCallController()

    init() {
        let config = CXProviderConfiguration()
        config.supportsVideo = false
        config.maximumCallsPerCallGroup = 1
        config.supportedHandleTypes = [.phoneNumber, .emailAddress]
        provider = CXProvider(configuration: config)
        super.init()
        provider.setDelegate(self, queue: nil)
    }

    func reportIncomingCall(uuid: UUID, callerName: String) {
        let update = CXCallUpdate()
        update.remoteHandle = CXHandle(type: .generic, value: callerName)
        update.hasVideo = false
        provider.reportNewIncomingCall(with: uuid, update: update) { error in
            // начинаем отвечать на звонок после разрешения системы
        }
    }
}

PushKit для входящих звонков в фоне. В отличие от обычных APNs push, PushKit будит приложение мгновенно и с высоким приоритетом. Но с iOS 13 Apple требует немедленно вызвать reportNewIncomingCall при получении VoIP push — иначе приложение завершается с crash. Нельзя делать сетевой запрос перед вызовом CallKit.

Android: ConnectionService и Telecom API

Android аналог CallKit — ConnectionService из пакета android.telecom. Позволяет приложению стать «телефонным аккаунтом» в системе, показывать звонки на экране блокировки, управлять аудиомаршрутизацией.

Для входящих звонков в фоне — FCM push с priority: high. На Android 14+ фоновые сервисы ограничены, но ForegroundService типа phoneCall (добавлен в Android 14) решает именно эту задачу — у него нет ограничений на запуск при входящем звонке.

Управление аудиосессией через AudioManager:

val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
audioManager.mode = AudioManager.MODE_IN_COMMUNICATION
audioManager.isSpeakerphoneOn = false
// при завершении:
audioManager.mode = AudioManager.MODE_NORMAL

Bluetooth-гарнитуры — отдельная головная боль. BluetoothHeadset profile, SCO соединение для голоса (не A2DP!), BroadcastReceiver на ACTION_SCO_AUDIO_STATE_UPDATED. Без явного управления SCO звук идёт через динамик даже при подключённой Bluetooth-гарнитуре.

WebRTC для медиаслоя

Если используем WebRTC самостоятельно (а не через Twilio/Vonage), нужен TURN-сервер для пробивания NAT. Без него звонки работают только в одной сети — классический баг на демо, который ломается у клиента за офисным NAT.

coturn — open source TURN сервер, разворачивается на VPS за несколько часов. Конфигурация ICE:

// Android WebRTC SDK
val iceServers = listOf(
    PeerConnection.IceServer.builder("stun:stun.example.com:3478").createIceServer(),
    PeerConnection.IceServer.builder("turn:turn.example.com:3478")
        .setUsername("user")
        .setPassword("password")
        .createIceServer()
)

Кодеки: Opus для аудио (адаптивный битрейт, хорошо работает при потерях пакетов). WebRTC SDK включает его по умолчанию.

Типичные ошибки в продакшне

Эхо. Появляется если AudioManager.MODE_IN_COMMUNICATION не установлен — система не включает echo cancellation. WebRTC SDK включает программный AEC, но аппаратный (через режим) надёжнее.

Звонок прерывается при входящем SMS. AVAudioSession на iOS теряет фокус. Нужно подписаться на AVAudioSessionInterruptionNotification и переактивировать сессию после прерывания.

Задержка > 300 мс. Обычно причина — TURN relay вместо прямого P2P соединения. Проверяем ICE candidate type в статистике WebRTC: relay вместо host или srflx.

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

Проектируем архитектуру под требования (managed SDK vs WebRTC), реализуем CallKit/ConnectionService интеграцию, настраиваем сигнальный протокол, медиатранспорт и TURN-сервер. Тестируем на реальных устройствах с разными сетевыми условиями, Bluetooth-гарнитурами, прерываниями.

Срок: 2–5 недель в зависимости от выбранного стека и требований к качеству звука.