Framework

CallKit

Display the system-calling UI for your app's VoIP services, and coordinate your calling services with other apps and the system.

Overview

CallKit lets you integrate your calling services with other call-related apps on the system. CallKit provides the calling interface, and you handle the back-end communication with your VoIP service. For incoming and outgoing calls, CallKit displays the same interfaces as the Phone app, giving your app a more native look and feel. And CallKit responds appropriately to system-level behaviors such as Do Not Disturb.

In addition to handling calls, you can provide a Call Directory app extension to provide caller ID information and a list of blocked numbers associated with your service.

Receiving an Incoming Call

To configure your app to receive incoming calls, first create a CXProvider object and store it for global access. An app reports an incoming call to the provider in response to an external notification, such as a VoIP push notification generated by PushKit.

Listing 1

Receiving a VoIP–related push notification

// MARK: PKPushRegistryDelegate
func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, forType type: PKPushType) {
    // report new incoming call
}

Using the information provided by the external notification, the app creates a UUID and a CXCallUpdate object to uniquely identify the call and the caller, and passes them both to the provider using the reportNewIncomingCall(with:update:completion:) method.

Listing 2

Handling an incoming call

if let uuidString = payload.dictionaryPayload["UUID"] as? String,
    let identifier = payload.dictionaryPayload["identifier"] as? String,
    let uuid = UUID(uuidString: uuidString)
{
    let update = CXCallUpdate()    
    update.callerIdentifier = identifier
    
    provider.reportNewIncomingCall(with: uuid, update: update) { error in
        // …
    }
}

After the call is connected, the system calls the provider(_:perform:) method of the provider delegate. In your implementation, the delegate is responsible for configuring an AVAudioSession and calling fulfill() on the action when finished.

Listing 3

Initiating the audio for a call

func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
    // configure audio session
    action.fulfill()
}

Making Outgoing Calls

A user can initiate an outgoing call with a VoIP app in any of the following ways:

  • Performing an interaction within the app

  • Opening a link with a supported custom URL scheme

  • Initiating a VoIP call using Siri

To make an outgoing call, an app requests a CXStartCallAction object from its CXCallController object. The action consists of a UUID to uniquely identify the call and a CXHandle object to specify the recipient.

Listing 4

Starting an outgoing call

let uuid = UUID()
let handle = CXHandle(type: .emailAddress, value: "jappleseed@apple.com")
 
let startCallAction = CXStartCallAction(call: uuid)
startCallAction.destination = handle
 
let transaction = CXTransaction(action: startCallAction)
callController.request(transaction) { error in
    if let error = error {
        print("Error requesting transaction: \(error)")
    } else {
        print("Requested transaction successfully")
    }
}

After the recipient answers the call, the system calls the provider(_:perform:) method of the the provider delegate. In your implementation of that method, configure an AVAudioSession and call the fulfill() method on the action object when finished.

Listing 5

Initiating the call

func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
    // configure audio session
    action.fulfill()
}

Call Blocking and Identification

Apps can create a Call Directory app extension to identify and block incoming callers by their phone number.

Creating a Call Directory App Extension

You can create a Call Directory extension for your containing app by adding a new project target and selecting the Call Directory Extension template under Application Extensions.

You set up both identification and blocking of incoming calls in the implementation of the beginRequest(with:) method of the CXCallDirectoryProvider subclass of your Call Directory extension. This method is called when the system launches the app extension.

For more information about how app extensions work, see App Extension Programming Guide.

Identifying Incoming Callers

When a phone receives an incoming call, the system first consults the user’s contacts to find a matching phone number. If no match is found, the system then consults your app’s Call Directory extension to find a matching entry to identify the phone number. This is useful for applications that maintain a contact list for a user that’s separate from the system contacts, such as a social network, or for identifying incoming calls that may be initiated from within the app, such as for customer service support or a delivery notification.

For example, consider a user who is friends with Jane in a social networking app, but who doesn’t have her phone number in their contacts. The social networking app has a Call Directory app extension, which downloads and adds the phone numbers of all of the user’s friends. Because of this, when the user gets an incoming call from Jane, the system displays something like “(App Name) Caller ID: Jane Appleseed” rather than “Unknown Caller”.

To provide identifying information about incoming callers, you use the addIdentificationEntry(withNextSequentialPhoneNumber:label:) method in the implementation of beginRequest(with:).

class CustomCallDirectoryProvider: CXCallDirectoryProvider {
    override func beginRequest(with context: CXCallDirectoryExtensionContext) {
        let labelsKeyedByPhoneNumber: [CXCallDirectoryPhoneNumber: String] = [ … ]
        for (phoneNumber, label) in labelsKeyedByPhoneNumber.sorted(by: <) {
            context.addIdentificationEntry(withNextSequentialPhoneNumber: phoneNumber, label: label)        
        }

        context.completeRequest()
    }
}

Because this method is called only when the system launches the app extension and not for each individual call, you must specify call identification information all at once; you cannot, for example, make a request to a web service to find information about an incoming call.

Blocking Incoming Calls

When a phone receives an incoming call, the system first consults the user’s block list to determine whether a call should be blocked. If the phone number is not on a user- or system-defined block list, the system then consults your app’s Call Directory extension to find a matching blocked number. This is useful for apps that, for example, maintain a database of known solicitors, or allow the user to block any numbers that match a set of criteria.

To block incoming calls for a particular phone number, you use the addBlockingEntry(withNextSequentialPhoneNumber:) method in the implementation of beginRequest(with:).

class CustomCallDirectoryProvider: CXCallDirectoryProvider {
    override func beginRequest(with context: CXCallDirectoryExtensionContext) {
        let blockedPhoneNumbers: [CXCallDirectoryPhoneNumber] = [ … ]
        for phoneNumber in blockedPhoneNumbers.sorted(by: <) {
            context.addBlockingEntry(withNextSequentialPhoneNumber: phoneNumber)
        }
        
        context.completeRequest()
    }
}

Topics

First Steps

Call-related actions are routed through your provider and its delegate, which you use to communicate with your service.

class CXProvider

An object that represents a telephony provider.

protocol CXProviderDelegate

A collection of methods that are called by a telephony provider object.

class CXProviderConfiguration

An encapsulation of the configuration of a provider object.

Incoming Calls

When a PushKit notification indicates an incoming call, you generate an appropriate action. CallKit handles the action by presenting the system interface for answering the call.

class CXAnswerCallAction

An encapsulation of the act of answering an incoming call.

class CXCallUpdate

An encapsulation of new and changed information about a call.

Outgoing Calls

Start outgoing calls with a call controller, and handle subsequent interactions with your provider delegate.

class CXCallController

A programmatic interface for interacting with and observing calls.

class CXTransaction

An object that contains zero or more action objects to be performed by a call controller.

class CXStartCallAction

An encapsulation of the act of initiating an outgoing call.

Call-Related Actions

Respond to actions reported by CallKit.

class CXAction

An abstract class that declares a programmatic interface for objects that represent a telephony action.

class CXCallAction

A programmatic interface for objects that represent a telephony action associated with a call object.

class CXEndCallAction

An encapsulation of the act of ending a call.

class CXPlayDTMFCallAction

An encapsulation of the act of playing a dual tone multifrequency (DTMF) sequence.

class CXSetGroupCallAction

An encapsulation of the act of grouping or ungrouping calls.

class CXSetHeldCallAction

An encapsulation of the act of placing a call on hold or removing a call from hold.

class CXSetMutedCallAction

An encapsulation of the act of muting or unmuting a call.

Call Information

Get information about calls, and be notified when the status of a call changes.

class CXCall

A telephony call.

class CXCallObserver

A programmatic interface for an object that manages a list of active calls and observes call changes.

protocol CXCallObserverDelegate

A collection of methods that are called by a call observer object when a call changes state.

class CXHandle

A means by which a call recipient can be reached, such as a phone number or email address.

Caller ID

Use a Call Directory app extension to block calls and provide caller ID information.

class CXCallDirectoryProvider

The principal object for a Call Directory app extension for a host app.

class CXCallDirectoryExtensionContext

A programmatic interface for adding identification and blocking entries to a Call Directory app extension.

protocol CXCallDirectoryExtensionContextDelegate

A collection of methods that are called by a Call Directory extension context object when a request fails.

class CXCallDirectoryManager

The programmatic interface to an object that manages a Call Directory app extension.