Complete Communications Engineering

Xamarin.iOS includes classes for CallKit that work similar to the CallKit framework in XCode.  Apple CallKit is an API that lets applications implement the same user interface for calling that other iOS phone apps use.  It can play a ringtone and display notifications when a call is received, and it can display a banner during calls to indicate that a call is active.  The main classes that the Xamarin application will use to interact with CallKit are CXProvider and CXCallController.  The CXProvider class handles CallKit configuration and is given a delegate that will handle events generated by CallKit.  It also handles incoming calls.  The CXCallController class is used to report user actions to CallKit such as starting an outgoing call or ending a current call.  The following is a minimal class that uses CallKit to interact with an application:

using System;

using CallKit;

using Foundation;

 

public class CallMgr_iOS : CXProviderDelegate

{

    private CXProvider provider;

    private CXCallController controller;

    private NSUuid current_call_uuid;

 

    public CallMgr_iOS()

    {

        NSNumber[] htypes = new NSNumber[] {

            (int)CXHandleType.PhoneNumber

        };

        CXProviderConfiguration config = new CXProviderConfiguration();

        config.MaximumCallGroups = 1;

        config.MaximumCallsPerCallGroup = 1;

        config.IncludesCallsInRecents = true;

        config.SupportsVideo = false;

        config.SupportedHandleTypes = new NSSet<NSNumber>(htypes);

        provider = new CXProvider(config);

        provider.SetDelegate(this, null);

        controller = new CXCallController();

    }

 

    public override void DidReset(CXProvider provider)

    {

        /* Nothing */

    }

 

    public override void PerformAnswerCallAction(CXProvider provider,

        CXAnswerCallAction action)

    {

        /* TODO – Accept the incoming call */

        action.Fulfill();

    }

 

    public override void PerformEndCallAction(CXProvider provider,

        CXEndCallAction action)

    {

        /* TODO – Reject the incoming call */

        current_call_uuid = null;

        action.Fulfill();

    }

 

    public void ReportIncomingCall(string number)

    {

        if (current_call_uuid != null) { return; }

        NSUuid uuid = new NSUuid(Guid.NewGuid().ToString());

        CXCallUpdate update = new CXCallUpdate();

        update.RemoteHandle = new CXHandle(CXHandleType.PhoneNumber,

                                           number);

        update.SupportsHolding = false;

        update.SupportsGrouping = false;

        update.SupportsUngrouping = false;

        update.HasVideo = false;

        update.SupportsDtmf = true;

        provider.ReportNewIncomingCall(uuid, update, (error) => {

            if (error == null) { current_call_uuid = uuid; }

        });

    }

 

    public void StartOutgoingCall(string number)

    {

        if (current_call_uuid != null) { return; }

        NSUuid uuid = new NSUuid(Guid.NewGuid().ToString());

        CXHandle handle = new CXHandle(CXHandleType.PhoneNumber, number);

        CXStartCallAction action = new CXStartCallAction(uuid, handle);

        CXTransaction transaction = new CXTransaction(action);

        controller.RequestTransaction(transaction, (error) => {

            if (error == null) { current_call_uuid = uuid; }

        });

    }

 

    public void EndCall()

    {

        if (current_call_uuid == null) { return; }

        CXEndCallAction action = new CXEndCallAction(current_call_uuid);

        CXTransaction transaction = new CXTransaction(action);

        controller.RequestTransaction(transaction, (error) => { });

        current_call_uuid = null;

    }

}

The class overrides the CXProviderDelegate class to handle CallKit events.  The constructor creates and configures a CXProvider instance and creates a CXCallController instance.  The public functions can be called by the application in response to the corresponding events.  The ReportIncomingCall function will pop-up the incoming call notification and let the user accept or reject the call.  Depending on the user’s choice, either PerformAnswerCallAction or PerformEndCallAction will be called by the provider delegate.  The StartOutgoingCall function will display the current call banner.  The EndCall function will remove the current call banner.