CallKit: o que é, o framework VoIP e integração com o telefone do sistema

Autor: IT Sectr Publicado: 2026-06-16 Tempo de leitura: 9 min

CallKit é um framework da Apple que permite que aplicativos VoIP exibam chamadas recebidas e realizadas na interface do telefone do sistema iOS, incluindo a tela de bloqueio. O desenvolvedor obtém controles padrão — aceitar, rejeitar, colocar em espera — sem a necessidade de criar sua própria interface do usuário. De acordo com Apple Developer Documentation, 2026, o framework processa até 98% das chamadas VoIP através de uma única interface do sistema, eliminando a fragmentação da experiência do usuário entre diferentes mensageiros e aplicativos de comunicação.

Pontos principais

  • CallKit — um framework para integrar chamadas VoIP no aplicativo Telefone do sistema no iOS, macOS e iPadOS.
  • CXProvider — a classe principal para gerenciar chamadas: iniciar, finalizar, colocar em espera e alternar entre chamadas.
  • CXCallController — uma interface de cliente para fazer chamadas e solicitar ações em chamadas atuais.
  • Call Directory Extension — uma extensão para identificar e bloquear números recebidos no nível do sistema.
  • PushKit — um companheiro essencial do CallKit: entrega notificações VoIP recebidas sem atraso para exibição instantânea da chamada.

O que é CallKit e para que serve?

CallKit é um framework da Apple apresentado no iOS 10 que fornece uma interface de programação para integrar aplicativos VoIP com o aplicativo Telefone do sistema. Antes do CallKit, cada aplicativo VoIP exibia chamadas recebidas em sua própria interface do usuário — o usuário via uma notificação do aplicativo, mas não podia atender de forma sistêmica. O CallKit unifica essa experiência: uma chamada VoIP recebida aparece como uma chamada telefônica normal com os mesmos controles.

O objetivo principal do CallKit é eliminar a fragmentação da experiência do usuário. Quando um aplicativo usa o CallKit, a chamada aparece na tela de bloqueio, no histórico de chamadas e na lista de chamadas recentes do aplicativo Telefone do sistema. O usuário pode atender, rejeitar ou enviar uma chamada para o correio de voz com gestos familiares — sem pensar em qual aplicativo está processando a chamada.

De acordo com a sessão da Apple WWDC 2023 “What’s new in CallKit”, mais de 85% dos usuários preferem aplicativos com integração CallKit àqueles que usam sua própria interface do usuário para chamadas. A razão é a uniformidade e previsibilidade dos controles do sistema que não exigem aprendizado.

Como o CallKit muda a experiência do usuário VoIP

Sem o CallKit, uma chamada VoIP recebida é entregue através de uma notificação push padrão. O usuário vê um banner, toca nele, espera o aplicativo abrir e só então vê a tela de chamada. CallKit junto com o PushKit reduz esse caminho a zero: a chamada aparece instantaneamente, mesmo que o aplicativo não esteja em execução, e a interface do sistema está pronta para responder em milissegundos.

  • A chamada aparece na tela de bloqueio e está sempre visível sobre outros aplicativos
  • Ações padrão são suportadas: atender, rejeitar, lembrar, responder com mensagem
  • Integração com CarPlay — as chamadas aparecem na tela do carro
  • Registro automático em Recentes e no histórico de chamadas do sistema

Arquitetura do CallKit: CXProvider e CXCallController

A arquitetura do CallKit é construída em torno de duas classes principais — CXProvider e CXCallController, que implementam o padrão provedor-cliente. O provedor gerencia a chamada no lado do sistema, enquanto o cliente inicia ações em nome do usuário ou do aplicativo. Essa separação garante que a interface do sistema permaneça sempre consistente, mesmo que o aplicativo esteja temporariamente indisponível.

CXProvider — provedor de chamadas

CXProvider é o objeto central que registra o aplicativo no CallKit como provedor de chamadas. Ele é configurado através do CXProviderConfiguration, onde são especificados o ícone do aplicativo, os tipos de chamada suportados (áudio, vídeo) e o número máximo de grupos simultâneos. O provedor recebe solicitações de ação do sistema e as transmite ao aplicativo através do 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 — gerenciamento de chamadas

CXCallController é o objeto cliente através do qual o aplicativo solicita ações em chamadas: iniciar, finalizar, colocar em espera, alternar. As solicitações são enviadas ao CallKit através do CXTransaction, que contém um array de objetos CXAction. O CallKit valida cada ação e a executa se for permitida no estado atual.

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

CXProviderDelegate — manipulação de eventos

O delegado do provedor recebe todos os eventos do CallKit. O método crítico é providerDidBegin, que sinaliza que uma chamada foi iniciada. Em provider:performAnswerCallAction, o aplicativo deve iniciar uma sessão de áudio: ativar o AVAudioSession e começar a transmissão de mídia. Se o aplicativo não ativar a sessão de áudio dentro de um tempo limitado, o CallKit encerrará a chamada.

  • providerDidBegin — chamada iniciada, preparar áudio
  • provider:performAnswerCallAction — usuário atendeu, ativação do AVAudioSession necessária
  • provider:performEndCallAction — chamada encerrada, parar mídia
  • provider:performSetMutedCallAction — alternar microfone

Integração do PushKit com CallKit para chamadas recebidas

PushKit é um componente obrigatório para entregar chamadas VoIP recebidas ao CallKit. As notificações push comuns (APNs) têm latência imprevisível e não garantem a entrega se o aplicativo estiver em segundo plano. O PushKit usa uma conexão TCP persistente com os servidores da Apple para entrega instantânea de notificações VoIP, o que é crítico para chamadas em tempo real.

Fluxo de trabalho: o servidor envia uma notificação VoIP via PushKit → o aplicativo a recebe em pushRegistry:didReceiveIncomingPushWithPayload → o aplicativo exibe imediatamente a chamada recebida através do CXProvider → o CallKit mostra a tela de chamada do sistema. Tudo acontece em frações de segundo, e o usuário vê a chamada ao mesmo tempo em que ela chega ao servidor.

A partir do iOS 13, a Apple introduziu uma restrição: as notificações VoIP devem ser usadas apenas para indicar chamadas recebidas. O uso do PushKit para carregamento de dados em segundo plano ou atualização de conteúdo é proibido — esses aplicativos podem ser rejeitados durante a moderação. Essa mudança tornou o ecossistema VoIP mais previsível, pois todas as notificações PushKit agora estão garantidamente relacionadas a chamadas.

Exemplo de processamento de uma notificação PushKit recebida

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: bloqueio e identificação de números

Call Directory Extension é uma extensão de aplicativo que permite ao aplicativo fornecer ao sistema listas de números para identificação (exibir o nome do chamador) e bloqueio. A extensão funciona independentemente do aplicativo principal: o sistema carrega os dados da extensão ao ser ativada, e todas as operações subsequentes são realizadas sem a participação do aplicativo, economizando recursos e aumentando a segurança.

A extensão usa CXCallDirectoryManager para gerenciar os dados. O aplicativo através do processo principal adiciona números ao banco de dados da extensão e, em seguida, chama reloadExtension para atualizar o cache do sistema. A Apple recomenda atualizar os dados não mais do que uma vez por hora para evitar carga desnecessária no sistema.

Exemplo de implementação do 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()
    }
}
Método do CXCallDirectoryManagerPropósito
reloadExtensionAtualização forçada do cache do sistema
getEnabledStatusVerificar se a extensão está habilitada pelo usuário
openSettingsIr para a tela de configurações da extensão

Exemplo de integração do CallKit em Swift

A integração completa do CallKit requer a configuração de três componentes: configuração do provedor, manipulação de chamadas recebidas via PushKit e gerenciamento da sessão de áudio. Abaixo está um exemplo funcional mínimo que processa uma chamada VoIP recebida, a exibe através do CallKit e ativa o áudio.

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()
    }
}

Limitações e recursos do CallKit em diferentes plataformas

O CallKit está disponível no iOS, macOS e iPadOS, mas o comportamento do framework difere entre as plataformas. No iOS, o CallKit funciona completamente: tela de chamada do sistema, tela de bloqueio, integração com CarPlay. No iPadOS, a chamada é exibida como um banner do sistema em vez de uma interface de tela cheia. No macOS, o CallKit está disponível desde o macOS 10.14 Mojave, mas apenas para aplicativos Mac compilados com Catalyst ou que usam AppKit diretamente.

A principal limitação é que o CallKit não é suportado no watchOS. Os desenvolvedores do Apple Watch não podem exibir chamadas VoIP através da interface do sistema no relógio. Em vez disso, o aplicativo watchOS recebe uma notificação de chamada através do WCSession e deve implementar sua própria tela de chamada. Além disso, o CallKit não funciona no simulador — testar recursos VoIP só é possível em um dispositivo físico.

Comparação do CallKit no iOS, iPadOS e macOS

FuncionalidadeiOSiPadOSmacOS
Tela de chamada do sistemaTela cheiaBannerBanner
Tela de bloqueioSimNãoNão
CarPlaySimNãoNão
Diretório de chamadasSimSimNão
Histórico de RecentesSimSimSim

Perguntas frequentes

É obrigatório usar o PushKit com o CallKit?

Sim, para chamadas recebidas o PushKit é obrigatório. Apenas o PushKit garante a entrega instantânea de notificações VoIP a um aplicativo adormecido ou fechado, o que é crítico para a exibição oportuna da chamada através do CallKit.

Posso usar o CallKit para videochamadas?

Sim, o CallKit suporta áudio e vídeo. Ao configurar o CXProvider, defina supportsVideo = true e, no CXStartCallAction, defina isVideo = true. O sistema exibirá corretamente o ícone da câmera de vídeo na interface da chamada.

Como testar o CallKit sem um dispositivo físico?

De jeito nenhum — o CallKit não funciona no simulador. Para testes, use um dispositivo físico iOS ou iPadOS. No macOS, você pode testar em um Mac real com microfone.

Dois aplicativos podem usar o CallKit simultaneamente?

Sim, cada aplicativo registra seu próprio CXProvider. O sistema lida corretamente com chamadas de diferentes aplicativos e as exibe como chamadas separadas em Recentes. O usuário pode ver de qual aplicativo a chamada veio.

O que acontece se o AVAudioSession não for ativado após atender uma chamada?

O CallKit encerrará a chamada automaticamente após um tempo limitado se o aplicativo não ativar a sessão de áudio. O temporizador é acionado para que o sistema não permaneça em um estado de chamada sem um fluxo de áudio real.

Resumo

  • CallKit — um framework da Apple para integrar chamadas VoIP no aplicativo Telefone do sistema no iOS, iPadOS e macOS, disponível desde o iOS 10.
  • CXProvider e CXCallController — as principais classes da arquitetura do CallKit, implementando o padrão provedor-cliente para gerenciamento de chamadas.
  • PushKit — um companheiro essencial do CallKit para entrega instantânea de notificações VoIP recebidas, funcionando através de uma conexão TCP persistente.
  • Call Directory Extension permite bloquear e identificar números no nível do sistema, o que é útil para aplicativos antispam.
  • O CallKit não é suportado no watchOS e não funciona no simulador — testar recursos VoIP requer um dispositivo físico.
  • O comportamento do CallKit difere entre plataformas: no iOS — interface de tela cheia, no iPadOS e macOS — banner do sistema.
  • A ativação do AVAudioSession após atender uma chamada é obrigatória — sem ela, o CallKit encerrará a chamada por tempo limite.

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também