CallKit 拒绝来电 (Objective-C)

CallKit Reject Inbound Call (Objective-C)

我正在使用 CallKit 开发一个 VOIP 应用程序(我们称之为 SampleApp),但遇到了一个问题。

我可以使用 CallKit 以一种看起来可以正常工作的方式接听入站 SampleApp 呼叫。但是,当我拒绝呼叫时,无论如何都会实例化呼叫,这是不正确的行为。

根据我的理解,我需要根据呼叫是否被接受和拒绝以某种方式获得一个布尔值,然后使用它来决定 phone 控制器是否接听来电。

PhoneViewController.m

- (void) presentIncomingCallAlertForCall:(SampleAppClientCall*)call
{
    callIdentifier = [[NSUUID alloc] init];
    // Use CallKit if iPhone
    if(UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad) 
    {
        [_pDelegate reportIncomingCall:callIdentifier 
                                handle:call.remoteAddress 
                              hasVideo:hasVideo 
                     completionHandler: nil];

        [self answerIncomingCall];
    }
    // Use Notification mechanism if iPad
    else 
    {
        // etc.
    }
}

ProviderDelegate.m

-(void) reportIncomingCall: (NSUUID *) uuid
                handle: (NSString *) handle
              hasVideo: (BOOL) hasVideo
     completionHandler:
     (nullable void (^) (NSArray * _Nullable results, NSError * _Nonnull error))completionHandler
{
    CXCallUpdate *update = [[CXCallUpdate alloc] init];
    update.remoteHandle = [[CXHandle alloc] initWithType:CXHandleTypePhoneNumber 
                                                   value:handle];
    update.hasVideo = hasVideo;

    [provider reportNewIncomingCallWithUUID:uuid 
                                     update:update 
                                 completion: ^(NSError *error)
    {
        // not sure what to put here? 
    }]; 
}

- (void) provider: (CXProvider *)provider 
     performAnswerCallAction : (CXAnswerCallAction *)action 
{
    NSDate *now = [[NSDate alloc] init];
    [action fulfillWithDateConnected: now];
}

这是我的第一个问题,我已经阅读了 Stack Overflow 指南,但如果我做错了什么请告诉我。

However, when I reject a call, the call is instantiated anyway, which is incorrect behaviour.

不清楚您在此处的代码中试图做什么。您总是在 [_pDelegate reportIncomingCall:...] 之后立即调用 [self answerIncomingCall];(我们看不到代码,但我假设向您的应用程序逻辑和后端报告用户已接听电话),所以看起来就像你假设用户已经决定回答它,甚至在用户做任何事情之前。

相反,您应该告诉您的应用程序逻辑和后端用户已接听电话,仅在您的 -provider:performAnswerCallAction: 方法和 -provider:performEndCallAction: 中,告诉您的应用程序逻辑和您的后端表明用户已拒绝来电(如果来电正在响铃)。

这是基于@user102008 的建议的解决方案,它实现了我想要实现的目标。

我将接听来电的责任移交给了提供者委托,而不是 phone 视图控制器,它会根据在其提供者方法。

PhoneViewController.m

- (void) presentIncomingCallAlertForCall:(SampleAppClientCall*)call {

    callIdentifier = [[NSUUID alloc] init];

    // Use CallKit if iPhone
    if(UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad) {
        [_pDelegate reportIncomingCall:callIdentifier 
                                handle:call.remoteAddress 
                              hasVideo:hasVideo 
                     completionHandler: nil];
    }
    // Use Notification mechanism if iPad
    else {
        ...
    }
}

ProviderDelegate.h

-(void) reportIncomingCall: (NSUUID *) uuid
                    handle: (NSString *) handle
                  hasVideo: (BOOL) hasVideo
         completionHandler: (nullable void (^) (NSArray * _Nullable results, NSError * _Nonnull error))
            completionHandler {

    CXCallUpdate *update = [[CXCallUpdate alloc] init];
    update.remoteHandle = [[CXHandle alloc] initWithType:CXHandleTypePhoneNumber value:handle];
    update.hasVideo = hasVideo;

    [provider reportNewIncomingCallWithUUID:uuid 
                                     update:update 
                                 completion: ^(NSError *error) {
        if (error) {
            [self reportCallEnded:uuid reason:(NSInteger *)CXCallEndedReasonFailed];
        }
    }];
}


- (void) provider: (CXProvider *)provider performAnswerCallAction: (CXAnswerCallAction *)action {
    [_phoneVC answerIncomingCall];
    NSDate *now = [[NSDate alloc] init];
    [action fulfillWithDateConnected: now];
}

- (void) provider: (CXProvider *)provider performEndCallAction: (CXEndCallAction *)action {
    [_phoneVC rejectIncomingCall];
    NSDate *now = [[NSDate alloc] init];
    [action fulfillWithDateEnded: now];
}