Реалізація CallKit для iOS (інтеграція з системними дзвінками)

Реалізація CallKit для iOS (інтеграція з системними дзвінками) Ми стикалися з ситуацією, коли VoIP-додаток отримував вхідний дзвінок, але користувач його пропускав, тому що системне сповіщення нічим не відрізнялося від звичайного банера. Результат — втрачені дзвінки та незадоволені клієнти. CallK

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

Це лише деякі з типів мобільних додатків, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1734 послуг
Реалізація CallKit для iOS (інтеграція з системними дзвінками)
Складний
~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

Реалізація CallKit для iOS (інтеграція з системними дзвінками)

Ми стикалися з ситуацією, коли VoIP-додаток отримував вхідний дзвінок, але користувач його пропускав, тому що системне сповіщення нічим не відрізнялося від звичайного банера. Результат — втрачені дзвінки та незадоволені клієнти. CallKit вирішує цю проблему, перетворюючи дзвінок додатка на повноцінний системний виклик з великим екраном, кнопками та записом в історію. У цій статті розповімо, як налаштувати CallKit з нуля, уникнути типових помилок і збільшити відсоток прийнятих дзвінків.

Як CallKit змінює взаємодію користувача з вхідним дзвінком?

Без CallKit вхідний VoIP-дзвінок виглядає як push-сповіщення. З CallKit — на весь екран, з можливістю відповісти або відхилити, з ім'ям контакту та фото. За статистикою, такий формат підвищує частку успішних з'єднань у 3-4 рази порівняно зі звичайним push-дзвінком.

Архітектура: CXProvider і CXCallController

Центральний клас — CXProvider. Він є точкою комунікації між додатком і системою: через нього повідомляємо про вхідний дзвінок, оновлюємо інформацію, завершуємо виклик. Другий клас — CXCallController, через який додаток ініціює вихідні дзвінки та керує ними.

let providerConfiguration = CXProviderConfiguration() providerConfiguration.supportsVideo = true providerConfiguration.maximumCallsPerCallGroup = 1 providerConfiguration.supportedHandleTypes = [.phoneNumber, .emailAddress, .generic] provider = CXProvider(configuration: providerConfiguration) provider.setDelegate(self, queue: nil) 

Вхідний дзвінок. Приходить через VoIP push (PushKit, не APNs). Це важливо: звичайний APNs push не підтримує CallKit-дзвінки з iOS 13 — Apple вимагає використовувати PKPushType.voIP і в делегаті PKPushRegistryDelegate.pushRegistry(_:didReceiveIncomingPushWith:) негайно викликати reportNewIncomingCall. Затримка між push і викликом reportNewIncomingCall — додаток завершується системою.

func reportIncomingCall(uuid: UUID, handle: String, hasVideo: Bool) { let update = CXCallUpdate() update.remoteHandle = CXHandle(type: .generic, value: handle) update.hasVideo = hasVideo provider.reportNewIncomingCall(with: uuid, update: update) { error in // якщо error != nil — система відхилила дзвінок (наприклад, DND) } } 

Відповідь/відхилення.

Система викликає CXProviderDelegate методи: provider(_:perform:) з CXAnswerCallAction або CXEndCallAction. У відповідь на AnswerAction потрібно підключити аудіо — запустити WebRTC сесію, підключити VoIP SDK (Twilio Voice, Agora, Daily).

WebRTC і аудіосесія

CallKit керує аудіосесією системи. Не можна налаштовувати AVAudioSession самостійно — це обов'язок CallKit. При відповіді на дзвінок система активує аудіосесію та викликає provider(_:didActivate:). У цей момент підключаємо аудіо-потік WebRTC до AVAudioSession. При завершенні — provider(_:didDeactivate:), відключаємо.

Якщо викликати AVAudioSession.setActive(true) раніше цього моменту — дзвінок може перерватися або аудіо не з'явиться. Типова помилка при першій інтеграції.

Twilio Voice SDK: TwilioVoice.handleNotificationcall.accept(with: delegate) → в callDidConnect активуємо аудіо через CallKit. SDK інкапсулює частину цієї логіки, але CXProvider все одно потрібен свій.

Історія дзвінків і Siri

Після завершення дзвінка викликаємо provider.reportCall(with: uuid, endedAt: Date(), reason: .remoteEnded). iOS автоматично додає запис в історію дзвінків «Телефону» з ім'ям і тривалістю. Користувач може передзвонити через «Телефон» — це виклик через додаток, якщо CXHandle типу .generic збігається з ідентифікатором.

Siri Shortcuts для дзвінків: через INStartCallIntent (iOS 13+) додаток реєструє намір. «Подзвони Івану через MyApp» — Siri запускає дзвінок через CallKit.

Типові проблеми

Дублювання дзвінків.

UUID має бути унікальним для кожного виклику і не змінюватися між push і відповіддю. Якщо push прийшов двічі (retry), перевіряємо UUID — не створюємо другий CXCallUpdate для того самого UUID.

Завислий дзвінок в історії. Якщо додаток крашнувся не викликавши reportCall(endedAt:), дзвінок залишається як «активний» в історії. Рішення: при наступному запуску додатка перевіряємо CXCallObserver.calls — якщо є незавершені, завершуємо їх.

VoIP Push на iOS 13+.

PKPushRegistry має бути ініціалізований в application(_:didFinishLaunchingWithOptions:), не ліниво. Apple перевіряє це і може завершити додаток.

Порівняння: CallKit vs звичайний push

Параметр Без CallKit З CallKit
Відображення дзвінка Банер push-сповіщення Повноекранний інтерфейс з ім'ям і фото
Кнопки дій Немає (тільки "Пізніше") Відповісти, Відхилити, Нагадування
Запис в історію Немає Автоматичний запис у "Телефон"
Відсоток відповідей ~20-30% ~70-80% (за даними клієнтів)

Статистика базується на документації Apple CallKit та реальних кейсах.

Як довго триває інтеграція CallKit?

Базова реалізація вхідного/вихідного дзвінка з одним VoIP SDK: 2-3 дні. З груповими дзвінками, відео, Siri Shortcuts та custom UI: 4-5 днів. Вартість розраховується після аналізу VoIP-інфраструктури та вимог. Зв'яжіться з нами — оцінимо ваш проект і запропонуємо оптимальне рішення.

Що входить у роботу

  • Налаштування CXProvider і CXCallController з конфігурацією під вимоги додатка
  • Інтеграція PushKit для VoIP push
  • Обробники відповіді, відхилення, завершення, hold, mute
  • Підключення до WebRTC/VoIP SDK (Twilio Voice, Agora, Daily, Vonage)
  • Аудіосесія через CallKit lifecycle
  • Запис в історію дзвінків
  • Обробка краш-сценаріїв і незавершених дзвінків

Ми гарантуємо коректну роботу CallKit відповідно до документації Apple. За 5+ років ми реалізували понад 30 проектів з VoIP і CallKit, тому знаємо всі підводні камені.