CallKit — Apple оквир који омогућава VoIP апликацијама да прикажу долазне и одлазне позиве у системском интерфејсу телефона iOS, укључујући екран закључавања. Програмер добија стандардне контроле — прихватање, одбијање, задржавање позива — без потребе за креирањем сопственог UI. Према Apple Developer Documentation, 2026, оквир обрађује до 98% VoIP позива кроз јединствени системски интерфејс, чиме се елиминише фрагментација корисничког искуства између различитих месенџера и комуникационих апликација.
Главне тачке
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 позив се доставља путем стандардног push обавештења. Корисник види банер, тапне на њега, чека отварање апликације и тек тада види екран позива. CallKit заједно са PushKit-ом скраћује овај пут на нулу: позив се појављује тренутно, чак и ако апликација није покренута, а системски интерфејс је спреман за одговор у милисекундама.
Архитектура CallKit-а је изграђена око две кључне класе — CXProvider и CXCallController, које реализују образац провајдер-клијент. Провајдер управља позивом на страни система, клијент покреће радње у име корисника или апликације. Ова подела гарантује да системски интерфејс увек остаје доследан, чак и ако је апликација привремено недоступна.
CXProvider — централни објекат који региструје апликацију у CallKit-у као провајдера позива. Конфигурише се кроз CXProviderConfiguration, где се наводе иконица апликације, подржани типови позива (аудио, видео) и максимални број истовремених група. Провајдер прима од система захтеве за радње и прослеђује их апликацији преко делегата CXProviderDelegate.
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 — клијентски објекат кроз који апликација захтева радње над позивима: започињање, завршетак, задржавање, пребацивање. Захтеви се прослеђују CallKit-у кроз CXTransaction, који садржи низ CXAction објеката. CallKit валидира сваку радњу и извршава је ако је дозвољена у тренутном стању.
let controller = CXCallController()
let startCallAction = CXStartCallAction(
callUUID: UUID(),
handle: CXHandle(type: .phoneNumber, value: "+15551234567")
)
startCallAction.isVideo = true
controller.request(CXTransaction(action: startCallAction))
Делегат провајдера прима све догађаје од CallKit-а. Критична метода — providerDidBegin, која сигнализира да је позив започет. У provider:performAnswerCallAction апликација треба да започне аудио сесију: активира AVAudioSession и започне пренос медија. Ако апликација не активира аудио сесију у ограниченом времену, CallKit ће завршити позив.
PushKit — обавезна компонента за достављање долазних VoIP позива у CallKit. Обична push обавештења (APNs) имају непредвидиво кашњење и не гарантују доставу ако је апликација у позадини. PushKit користи сталну TCP везу са Apple серверима за тренутну доставу VoIP обавештења, што је критично за позиве у реалном времену.
Шема рада: сервер шаље VoIP обавештење путем PushKit-а → апликација га прима у pushRegistry:didReceiveIncomingPushWithPayload → апликација одмах приказује долазни позив кроз CXProvider → CallKit приказује системски екран позива. Све се дешава у делићу секунде, а корисник види позив истовремено са његовим пристизањем на сервер.
Почев од iOS 13, Apple је увео ограничење: VoIP обавештења треба користити само за индикацију долазних позива. Коришћење PushKit-а за позадинско учитавање података или ажурирање садржаја је забрањено — такве апликације могу бити одбијене при модерацији. Ова промена је учинила VoIP екосистем предвидљивијим, јер су сада сва PushKit обавештења гарантовано повезана са позивима.
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 — проширење апликације које омогућава апликацији да пружи систему листе бројева за идентификацију (приказ имена позиваоца) и блокирање. Проширење ради независно од главне апликације: систем учитава податке из проширења при активацији, а све даље операције се извршавају без учешћа апликације, што штеди ресурсе и повећава безбедност.
Проширење користи CXCallDirectoryManager за управљање подацима. Апликација кроз главни процес додаје бројеве у базу података проширења, а затим позива reloadExtension за ажурирање системског кеша. Apple препоручује ажурирање података не чешће од једном на сат како би се избегло непотребно оптерећење система.
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-а захтева подешавање три компоненте: конфигурацију провајдера, обраду долазних позива кроз PushKit и управљање аудио сесијом. Испод је минимални радни пример који обрађује долазни VoIP позив, приказује га кроз CallKit и активира аудио.
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 је доступан на 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 функција је могуће само на физичком уређају.
| Функција | iOS | iPadOS | macOS |
|---|---|---|---|
| Системски екран позива | Цео екран | Банер | Банер |
| Закључани екран | Да | Не | Не |
| CarPlay | Да | Не | Не |
| Call Directory | Да | Да | Не |
| Историја Recents | Да | Да | Да |
Често постављана питања
Да, за долазне позиве PushKit је обавезан. Само PushKit гарантује тренутну доставу VoIP обавештења успаваној или затвореној апликацији, што је критично за благовремено приказивање позива кроз CallKit.
Да, CallKit подржава аудио и видео. При конфигурацији CXProvider поставите supportsVideo = true, а у CXStartCallAction поставите isVideo = true. Систем ће исправно приказати иконицу камере у интерфејсу позива.
Никако — CallKit не ради на симулатору. За тестирање користите физички iOS или iPadOS уређај. На macOS-у можете тестирати на правом Mac-у са микрофоном.
Да, свака апликација региструје сопствени CXProvider. Систем исправно обрађује позиве из различитих апликација и приказује их као одвојене позиве у Recents-у. Корисник види из које апликације је позив дошао.
CallKit ће аутоматски завршити позив након ограниченог времена ако апликација не активира аудио сесију. Тајмер се покреће како систем не би остао у стању позива без стварног аудио тока.
Резиме
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође