Search code examples
ioscallkit

CallKit: how to differentiate between decline call and end connected call


Suppose an app supports two calls at a time. the first call is connected and second call is coming in. one gets "end call & answer call", "decline", "hold call and answer call" buttons.

In case of "end call & answer call", it means to end the connected call and answer the new call. In case of "decline", it means to reject the incomming call.

In both cases the delegate

- (void)provider:(CXProvider *)provider performEndCallAction:(CXEndCallAction *)action

is triggered. Now, How do one should know which one of those calls to end, the incoming call or the call already connected? The CXEndCallAction doesnt state a reason for either "decline" nor "end-already-connected call"

does anyone have a solution?


Solution

  • I found out that there is a transaction list delegate:

    - (BOOL)provider:(CXProvider *)provider executeTransaction:(CXTransaction *)transaction
    

    implementing this delegate will give enough information if there is a transaction that will trigger the other delegates such CXSetHeldCallAction or CXEndCallAction. so now I can decide what action is to trigger, and bypassing other delegates if necessary.

    here is my code if anyone else is struggling:

    - (BOOL)provider:(CXProvider *)provider executeTransaction:(CXTransaction *)transaction
    {
    NSLog(@"executeTransaction : %@", transaction.debugDescription);
    BOOL callEnd = NO;
    BOOL callHold= NO;
    BOOL callAnswer = NO;
    
    NSPredicate *filter = [NSPredicate predicateWithFormat:@"self isKindOfClass: %@", [CXEndCallAction class]];
    NSArray *ends = [transaction.actions filteredArrayUsingPredicate:filter];
    callEnd = [ends count] >= 1;
    
    filter = [NSPredicate predicateWithFormat:@"self isKindOfClass: %@", [CXAnswerCallAction class]];
    NSArray *answer = [transaction.actions filteredArrayUsingPredicate:filter];
    callAnswer = [answer count] >= 1;
    
    filter = [NSPredicate predicateWithFormat:@"self isKindOfClass: %@", [CXSetHeldCallAction class]];
    NSArray *hold = [transaction.actions filteredArrayUsingPredicate:filter];
    callHold = [hold count] >= 1;
    
    if(callEnd && callAnswer)
    {
        actionType = kCallKitEndAndAnswer;
        [[MyCallManager sharedManager] endPreviousCallAndAnswerNewCall:^(BOOL succeeded) {
            NSLog(@"end answered call: %@", succeeded ? @"yes" : @"No");
            CXEndCallAction *en = [ends firstObject];
            succeeded ? [en fulfill] : [en fail];
    
            CXAnswerCallAction *an= [answer firstObject];
            succeeded ? [an fulfill] : [an fail];
    
        }];
        return YES;
    }
    else if(callHold && callAnswer)
    {
        actionType = kCallKitHoldAndAnswer;
    
        [[MyCallManager sharedManager] answerCall:^(BOOL succeeded) {
            NSLog(@"hold answered call: %@", succeeded ? @"yes" : @"No");
            CXSetHeldCallAction *ho = [hold firstObject];
            succeeded ? [ho fulfill] : [ho fail];
    
            CXAnswerCallAction *an= [answer firstObject];
            succeeded ? [an fulfill] : [an fail];
        }];
        return YES;
    }
    else if([hold count] == 2)
    {
        [[MyCallManager sharedManager] swapCalls];
        usleep(25000);
        CXSetHeldCallAction * fi = [hold firstObject];
        CXSetHeldCallAction * la = [hold lastObject];
        [fi fulfill];
        [la fulfill];
    
        return YES;
    }
    
    return NO;
    }