CallKit – How to Configure It?
iOS 10 offers many new features. One of them is CallKit, the framework which allows our application to seamlessly integrate with the user interface of a phone. CallKit may be used in applications to let users receive incoming calls and perform outgoing calls with the phone-provided UI. VoIP call can be muted or suspended. It is also possible to make video calls.
Preparing the project
The first step is to prepare receiving VoIP notifications.
Configuring VoIP notifications
To configure the application to receive notifications, import framework PushKit to our AppDelegate file and create an object PKPushRegistry. Be sure to set the delegate of the newly created object as self, and set its type as VoIP:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
let pushRegistry = PKPushRegistry(queue: DispatchQueue.main)
pushRegistry.delegate = self
pushRegistry.desiredPushTypes = [.voIP]
return true
}
Functions used for storing credentials on the server for the active user and processing pushs are:
func pushRegistry(_ registry: PKPushRegistry, didUpdate credentials: PKPushCredentials, forType type: PKPushType) {
//Store push credentials on server for the active user.
}
func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, forType type: PKPushType) {
}
Supporting received notifications
The final step is to parse the data received from the function didReceiveIncomingPushWith, which, among other things, can wake the phone from the state of being locked.
func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, forType type: PKPushType) {
guard type == .voIP else { return }
if let uuidString = payload.dictionaryPayload["UUID"] as? String,
let handle = payload.dictionaryPayload["handle"] as? String,
let hasVideo = payload.dictionaryPayload["hasVideo"] as? Bool,
let uuid = UUID(uuidString: uuidString)
{
// Handle incoming call
}
}
Setting up CallKit
The first step is to create a class to handle incoming calls by extending the class CXProviderDelegate.
final class ProviderDelegate: NSObject, CXProviderDelegate {
private let provider: CXProvider
}
The next step is to configure the provider.
static var providerConfiguration: CXProviderConfiguration {
let localizedName = NSLocalizedString("APPLICATION_NAME", comment: "name")
let providerConfiguration = CXProviderConfiguration(localizedName: localizedName)
providerConfiguration.supportsVideo = true
providerConfiguration.maximumCallsPerCallGroup = 1
providerConfiguration.supportedHandleTypes = [.phoneNumber]
if let iconMaskImage = UIImage(named: "wideo") {
providerConfiguration.iconTemplateImageData = UIImagePNGRepresentation(iconMaskImage)
}
providerConfiguration.ringtoneSound = "Ringtone.caf"
return providerConfiguration
}
The last step is to provide an initializer, add the reportIncomingCall function responsible for the transfer of an incoming call to the system and to add providerDidReset function which is called when the provider is restarted.
init() {
provider = CXProvider(configuration: type(of: self).providerConfiguration)
super.init()
provider.setDelegate(self, queue: nil)
}
func reportIncomingCall(uuid: UUID, handle: String, hasVideo: Bool = false, completion: ((NSError?) -> Void)? = nil) {
// Construct a CXCallUpdate describing the incoming call, including the caller.
let update = CXCallUpdate()
update.remoteHandle = CXHandle(type: .phoneNumber, value: handle)
update.hasVideo = hasVideo
// Report the incoming call to the system
provider.reportNewIncomingCall(with: uuid, update: update) { error in
completion?(error as? NSError)
}
}
func providerDidReset(_ provider: CXProvider) {
print("Provider did reset")
/*
End any ongoing calls if the provider resets, and remove them from the app's list of calls,
since they are no longer valid.
*/
}
This is only an introduction, and if you would like to learn more about this, I recommend reading this.
You can find a lot of information and a sample application there.