CallKit & PushKit

CallKit e PushKit per Chiamate VoIP in Background: Gestione dello Stato di Chiamata ed Interfaccia Nativa iOS

Affinché un'applicazione iOS di fonia (come WhatsApp, Skype o **Africall**) possa squillare ed essere risposta a schermo bloccato con la medesima schermata verde/rossa delle chiamate telefoniche di sistema, è indispensabile utilizzare l'accoppiata di framework Apple PushKit e CallKit.

1. Registrazione del PushKit VoIP Token

PushKit fornisce un tipo di notifica push ad altissima priorità che risveglia l'app dallo stato di sospensione o kill. A differenza delle notifiche push standard (APNs), una notifica PushKit **deve obbligatoriamente notificare CallKit** entro pochi millisecondi per evitare sanzioni da parte del sistema operativo:

import Foundation
import PushKit
import CallKit

class VoIPPushManager: NSObject, PKPushRegistryDelegate {
    static let shared = VoIPPushManager()
    private var voipRegistry: PKPushRegistry?

    func registerForVoIPPushNotifications() {
        voipRegistry = PKPushRegistry(queue: DispatchQueue.main)
        voipRegistry?.delegate = self
        voipRegistry?.desiredPushTypes = [.voIP]
    }

    // Ricezione token PushKit da Apple
    func pushRegistry(_ registry: PKPushRegistry, didUpdate pushCredentials: PKPushCredentials, for type: PKPushType) {
        let token = pushCredentials.token.map { String(format: "%02.2hhx", $0) }.joined()
        print("Token PushKit VoIP generato: \(token)")
    }

    // Ricezione notifica VoIP in background
    func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) {
        guard let callerName = payload.dictionaryPayload["callerName"] as? String,
              let callUUIDString = payload.dictionaryPayload["callUUID"] as? String,
              let callUUID = UUID(uuidString: callUUIDString) else {
            completion()
            return
        }

        // Segnala IMMEDIATAMENTE la chiamata in arrivo a CallKit
        CallKitManager.shared.reportIncomingCall(uuid: callUUID, handle: callerName) {
            completion()
        }
    }
}

2. Configurazione di CXProvider e Controller CallKit in Swift

CXProvider è l'oggetto responsabile della comunicazione con l'interfaccia telefonica nativa dell'iPhone:

import CallKit
import AVFoundation

class CallKitManager: NSObject, CXProviderDelegate {
    static let shared = CallKitManager()
    private var provider: CXProvider?
    private var callController = CXCallController()

    override init() {
        super.init()
        let config = CXProviderConfiguration(localizedName: "AfriCall VoIP")
        config.supportsVideo = false
        config.maximumCallGroups = 1
        config.supportedHandleTypes = [.phoneNumber]
        
        provider = CXProvider(configuration: config)
        provider?.setDelegate(self, queue: nil)
    }

    func reportIncomingCall(uuid: UUID, handle: String, completion: @escaping () -> Void) {
        let update = CXCallUpdate()
        update.remoteHandle = CXHandle(type: .phoneNumber, value: handle)
        update.hasVideo = false

        provider?.reportNewIncomingCall(with: uuid, update: update) { error in
            if error == nil {
                print("Chiamata nativa iOS notificata a schermo bloccato!")
            }
            completion()
        }
    }

    // Delegate Methods
    func providerDidReset(_ provider: CXProvider) {}

    func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
        // L'utente ha premuto il tasto verde di risposta nativo
        action.fulfill()
    }

    func provider(_ provider: CXProvider, perform action: CXEndCallAction) {
        // L'utente ha agganciato la chiamata
        action.fulfill()
    }
}

Conclusione

L'integrazione di CallKit e PushKit garantisce un'esperienza utente nativa per chiamate VoIP di livello professionale. Per integrare CallKit nelle tue applicazioni iOS, scrivi a diallooyunus@gmail.com.

Yunus Diallo (DialloDev)

Fondatore di Dywtal Digital a Parma (Italia), sviluppatore iOS specializzato in telecomunicazioni mobile, CallKit e PushKit.