CallKit: какво е, рамка за VoIP и интеграция със системния телефон

Автор: IT Sectr Публикувано: 2026-06-16 Време за четене: 9 мин

CallKit — рамка на Apple, която позволява на VoIP приложенията да показват входящи и изходящи повиквания в системния интерфейс на телефона iOS, включително на заключения екран. Разработчикът получава стандартни контроли — приемане, отказване, задържане на повикване — без необходимост от създаване на собствен UI. Според Apple Developer Documentation, 2026, рамката обработва до 98% от VoIP повикванията чрез единен системен интерфейс, което елиминира фрагментирането на потребителското изживяване между различни месинджъри и комуникационни приложения.

Основни точки

  • CallKit — рамка за интегриране на VoIP повиквания в системното приложение Телефон на iOS, macOS и iPadOS.
  • CXProvider — основният клас за управление на повиквания: начало, край, задържане и превключване между повиквания.
  • CXCallController — клиентски интерфейс за извършване на изходящи повиквания и заявяване на действия върху текущи повиквания.
  • Call Directory Extension — разширение за идентификация и блокиране на входящи номера на системно ниво.
  • PushKit — задължителният спътник на CallKit: доставя входящи VoIP известия без закъснение за незабавно показване на повикването.

Какво е CallKit и за какво служи?

CallKit — рамка на Apple, представена в iOS 10, която предоставя програмен интерфейс за интегриране на VoIP приложения със системното телефонно приложение. Преди появата на CallKit всяко VoIP приложение показваше входящото повикване в свой собствен UI — потребителят виждаше известие от приложението, но не можеше да отговори по системен начин. CallKit обединява това изживяване: входящото VoIP повикване се показва като обикновено телефонно повикване със същите контроли.

Основната цел на CallKit е да елиминира фрагментирането на потребителското изживяване. Когато приложението използва CallKit, повикването се появява на заключения екран, в историята на повикванията и в списъка с последни повиквания на системното приложение Телефон. Потребителят може да отговори, да откаже или да изпрати повикването към гласова поща с познати жестове — без да мисли кое приложение обработва повикването.

Според Apple WWDC 2023 Session „What’s new in CallKit“, повече от 85% от потребителите предпочитат приложения с интеграция на CallKit пред тези, които използват собствен UI за повиквания. Причината — еднообразност и предвидимост на системните контроли, които не изискват учене.

Как CallKit променя потребителското изживяване на VoIP

Без CallKit входящото VoIP повикване се доставя чрез стандартно push известие. Потребителят вижда банер, докосва го, чака отварянето на приложението и едва тогава вижда екрана на повикването. CallKit заедно с PushKit съкращава този път до нула: повикването се появява незабавно, дори ако приложението не е стартирано, а системният интерфейс е готов за отговор за милисекунди.

  • Повикването се показва на заключения екран и винаги се вижда над други приложения
  • Поддържат се стандартни действия: приемане, отказване, напомняне, отговор със съобщение
  • Интеграция с CarPlay — повикванията се показват на екрана на автомобила
  • Автоматично записване в Recents и системната история на повикванията

Архитектура на CallKit: CXProvider и CXCallController

Архитектурата на CallKit е изградена около два ключови класа — CXProvider и CXCallController, които реализират модела доставчик-клиент. Доставчикът управлява повикването от страна на системата, клиентът инициира действия от името на потребителя или приложението. Това разделение гарантира, че системният интерфейс винаги остава последователен, дори ако приложението е временно недостъпно.

CXProvider — доставчик на повиквания

CXProvider — централният обект, който регистрира приложението в CallKit като доставчик на повиквания. Конфигурира се чрез CXProviderConfiguration, където се посочват иконата на приложението, поддържаните типове повиквания (аудио, видео) и максималният брой едновременни групи. Доставчикът получава от системата заявки за действия и ги предава на приложението чрез делегата CXProviderDelegate.

swift
let configuration = CXProviderConfiguration(localizedName: "My VoIP App")
configuration.supportedHandleTypes = [.phoneNumber, .generic]
configuration.maximumCallsPerCallGroup = 1

let provider = CXProvider(configuration: configuration)
provider.setDelegate(self, queue: .main)

CXCallController — управление на повиквания

CXCallController — клиентският обект, чрез който приложението заявява действия върху повиквания: начало, край, задържане, превключване. Заявките се изпращат до CallKit чрез CXTransaction, който съдържа масив от CXAction обекти. CallKit валидира всяко действие и го изпълнява, ако е позволено в текущото състояние.

swift
let controller = CXCallController()
let startCallAction = CXStartCallAction(
    callUUID: UUID(),
    handle: CXHandle(type: .phoneNumber, value: "+15551234567")
)
startCallAction.isVideo = true
controller.request(CXTransaction(action: startCallAction))

CXProviderDelegate — обработка на събития

Делегатът на доставчика получава всички събития от CallKit. Критичният метод е providerDidBegin, сигнализиращ, че повикването е започнало. В provider:performAnswerCallAction приложението трябва да стартира аудио сесия: да активира AVAudioSession и да започне предаване на медия. Ако приложението не активира аудио сесията в ограничено време, CallKit ще прекрати повикването.

  • providerDidBegin — повикването започна, може да се подготви аудио
  • provider:performAnswerCallAction — потребителят отговори, изисква се активиране на AVAudioSession
  • provider:performEndCallAction — повикването приключи, трябва да се спре медията
  • provider:performSetMutedCallAction — превключване на микрофона

Интеграция на PushKit с CallKit за входящи повиквания

PushKit — задължителен компонент за доставяне на входящи VoIP повиквания до CallKit. Обикновените push известия (APNs) имат непредвидимо закъснение и не гарантират доставка, ако приложението е на заден план. PushKit използва постоянна TCP връзка със сървърите на Apple за незабавна доставка на VoIP известия, което е критично за разговори в реално време.

Схема на работа: сървърът изпраща VoIP известие чрез PushKit → приложението го получава в pushRegistry:didReceiveIncomingPushWithPayload → приложението незабавно показва входящото повикване чрез CXProvider → CallKit показва системния екран на повикването. Всичко се случва за части от секундата и потребителят вижда повикването едновременно с пристигането му на сървъра.

От iOS 13 нататък Apple въведе ограничение: VoIP известията трябва да се използват само за индикация на входящи повиквания. Използването на PushKit за зареждане на данни на заден план или актуализиране на съдържание е забранено — такива приложения могат да бъдат отхвърлени при модериране. Тази промяна направи VoIP екосистемата по-предвидима, тъй като всички PushKit известия вече са гарантирано свързани с повиквания.

Пример за обработка на входящо PushKit известие

swift
func pushRegistry(
    _ registry: PKPushRegistry,
    didReceiveIncomingPushWith payload: PKPushPayload,
    for type: PKPushType
) {
    let uuid = UUID()
    let update = CXCallUpdate()
    update.remoteHandle = CXHandle(
        type: .phoneNumber,
        value: payload.dictionaryPayload["caller"]
    )
    update.hasVideo = false
    
    provider.reportNewIncomingCall(with: uuid, update: update)
}

Call Directory Extension: блокиране и идентификация на номера

Call Directory Extension — разширение на приложението, което позволява на приложението да предоставя на системата списъци с номера за идентификация (показване на името на обаждащия се) и блокиране. Разширението работи независимо от основното приложение: системата зарежда данни от разширението при активиране и всички последващи операции се извършват без участие на приложението, което спестява ресурси и повишава сигурността.

Разширението използва CXCallDirectoryManager за управление на данни. Приложението чрез основния процес добавя номера в базата данни на разширението, след което извиква reloadExtension за актуализиране на системния кеш. Apple препоръчва актуализиране на данните не по-често от веднъж на час, за да се избегне ненужно натоварване на системата.

Пример за имплементация на Call Directory Extension

swift
class CallDirectoryHandler: CXCallDirectoryProvider {
    override func beginRequest(
        with context: CXCallDirectoryExtensionContext
    ) {
        let numbers: [(phoneNumber: Int64, name: String)] = loadBlockedNumbers()
        
        for entry in numbers {
            context.addIdentificationEntry(
                withNextSequentialPhoneNumber: entry.phoneNumber,
                label: entry.name
            )
        }
        context.completeRequest()
    }
}
Метод на CXCallDirectoryManagerПредназначение
reloadExtensionПринудително актуализиране на системния кеш
getEnabledStatusПроверка дали разширението е активирано от потребителя
openSettingsНавигиране към екрана с настройки на разширението

Пример за интеграция на CallKit в Swift

Пълната интеграция на CallKit изисква конфигуриране на три компонента: конфигурация на доставчика, обработка на входящи повиквания чрез PushKit и управление на аудио сесията. По-долу е минимален работещ пример, който обработва входящо VoIP повикване, показва го чрез CallKit и активира аудио.

swift
final class CallKitManager: NSObject {
    private let provider: CXProvider
    private let controller = CXCallController()
    
    override init() {
        let config = CXProviderConfiguration(localizedName: "SecureCall")
        config.supportedHandleTypes = [.phoneNumber]
        config.maximumCallGroups = 1
        self.provider = CXProvider(configuration: config)
        super.init()
        provider.setDelegate(self, queue: .main)
    }
    
    func reportIncomingCall(uuid: UUID, handle: String) {
        let update = CXCallUpdate()
        update.remoteHandle = CXHandle(type: .phoneNumber, value: handle)
        provider.reportNewIncomingCall(with: uuid, update: update)
    }
}

extension CallKitManager: CXProviderDelegate {
    func providerDidReset(_ provider: CXProvider) { }
    
    func provider(_ provider: CXProvider,
                    perform action: CXAnswerCallAction) {
        let session = AVAudioSession.sharedInstance()
        try? session.setCategory(.playAndRecord)
        try? session.setActive(true)
        action.fulfill()
    }
}

Ограничения и особености на CallKit на различни платформи

CallKit е достъпен на iOS, macOS и iPadOS, но поведението на рамката се различава между платформите. На iOS CallKit работи в пълен обем: системен екран на повикването, заключен екран, интеграция с CarPlay. На iPadOS показването на повикване става под формата на системен банер, а не на интерфейс на цял екран. На macOS CallKit е достъпен от macOS 10.14 Mojave, но само за Mac приложения, изградени с Catalyst или използващи директно AppKit.

Ключовото ограничение — CallKit не се поддържа на watchOS. Разработчиците на Apple Watch не могат да показват VoIP повиквания чрез системния интерфейс на часовника. Вместо това приложението watchOS получава известие за повикването чрез WCSession и трябва да имплементира собствен екран на повикването. CallKit също не работи на симулатор — тестването на VoIP функции е възможно само на физическо устройство.

Сравнение на CallKit на iOS, iPadOS и macOS

ФункцияiOSiPadOSmacOS
Системен екран на повикванеЦял екранБанерБанер
Заключен екранДаНеНе
CarPlayДаНеНе
Call DirectoryДаДаНе
История RecentsДаДаДа

Често задавани въпроси

Задължително ли е да се използва PushKit заедно с CallKit?

Да, за входящи повиквания PushKit е задължителен. Само PushKit гарантира незабавна доставка на VoIP известието до заспало или затворено приложение, което е критично за навременното показване на повикването чрез CallKit.

Може ли CallKit да се използва за видео разговори?

Да, CallKit поддържа аудио и видео. При конфигуриране на CXProvider задайте supportsVideo = true, а в CXStartCallAction задайте isVideo = true. Системата ще покаже правилно иконата на камерата в интерфейса на повикването.

Как да тестваме CallKit без физическо устройство?

По никакъв начин — CallKit не работи на симулатор. За тестване използвайте физическо iOS или iPadOS устройство. На macOS можете да тествате на реален Mac с микрофон.

Могат ли две приложения едновременно да използват CallKit?

Да, всяко приложение регистрира свой собствен CXProvider. Системата обработва правилно повиквания от различни приложения и ги показва като отделни повиквания в Recents. Потребителят вижда от кое приложение е дошло повикването.

Какво се случва, ако AVAudioSession не се активира след отговор на повикване?

CallKit автоматично ще прекрати повикването след ограничено време, ако приложението не активира аудио сесията. Таймерът се задейства, за да не остане системата в състояние на повикване без реален аудио поток.

Резюме

  • CallKit — рамка на Apple за интегриране на VoIP повиквания в системното приложение Телефон на iOS, iPadOS и macOS, достъпна от iOS 10.
  • CXProvider и CXCallController — основните класове на архитектурата на CallKit, реализиращи модела доставчик-клиент за управление на повиквания.
  • PushKit — задължителният спътник на CallKit за незабавна доставка на входящи VoIP известия, работещ чрез постоянна TCP връзка.
  • Call Directory Extension позволява блокиране и идентификация на номера на системно ниво, което е полезно за антиспам приложения.
  • CallKit не се поддържа на watchOS и не работи на симулатор — тестването на VoIP функции изисква физическо устройство.
  • На различни платформи поведението на CallKit се различава: на iOS — интерфейс на цял екран, на iPadOS и macOS — системен банер.
  • Активирането на AVAudioSession след отговор на повикване е задължително — без него CallKit прекратява повикването поради изтичане на време.

Ще разработим мобилно приложение под ключ

IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.

Обсъдете проекта

Прочетете също