Hi,
We've run into an issue where we are getting the CXErrorCodeRequestTransactionErrorUnknownCallUUID error while ending an outbound VoIP call during an interruption:
Received reply from transaction request with error: Error Domain=com.apple.CallKit.error.requesttransaction Code=4 "(null)"
We've also checked that the call UUIDs used for starting the call, updating connection status and ending the call are all the same, which makes us wonder what else could have gone wrong. Here are the steps to reproduce the error:
- Initiate a PSTN outbound call and answer on the call receiver side
- Back to my application and initiate an outbound VoIP call
- The PSTN call will be interrupted and put on hold
- Disconnect the VoIP call after it is connected
and then I received the error while requesting the CXEndCallAction transaction. Somehow this only happens when there is an interruption.
Code flow in the app:
1. Request CXStartCallAction to the CallKit call controller:
// uuid = [NSUUID UUID];
- (void)performStartCallActionWithUUID:(NSUUID *)uuid handle:(NSString *)handle {
CXHandle *callHandle = [[CXHandle alloc] initWithType:CXHandleTypeGeneric value:handle];
CXStartCallAction *startCallAction = [[CXStartCallAction alloc] initWithCallUUID:uuid handle:callHandle];
CXTransaction *transaction = [[CXTransaction alloc] initWithAction:startCallAction];
[self.callKitCallController requestTransaction:transaction completion:^(NSError *error) {
if (error) {
NSLog(@"Failed to submit start-call transaction request");
} else {
CXCallUpdate *callUpdate = [[CXCallUpdate alloc] init];
callUpdate.remoteHandle = callHandle;
callUpdate.supportsDTMF = YES;
callUpdate.supportsHolding = YES;
callUpdate.supportsGrouping = NO;
callUpdate.supportsUngrouping = NO;
callUpdate.hasVideo = NO;
[self.callKitProvider reportCallWithUUID:uuid updated:callUpdate];
}
}];
}
2.Initiate VoIP in the provider delegate callback:
(VoIP call is made inside the performVoiceCallWithAction method)
- (void)provider:(CXProvider *)provider performStartCallAction:(CXStartCallAction *)action {
// some AVAudioSession and audio unit manipulation based on CallKit guideline
[self.callKitProvider reportOutgoingCallWithUUID:action.callUUID startedConnectingAtDate:[NSDate date]];
__weak typeof(self) weakSelf = self;
[self performVoiceCallWithAction:action completion:^(BOOL success) {
__strong typeof(self) strongSelf = weakSelf;
if (success) {
[strongSelf.callKitProvider reportOutgoingCallWithUUID:action.callUUID connectedAtDate:[NSDate date]];
[action fulfill];
} else {
[action fail];
}
}];
}
3. Once the call is connected (signaling and media connection established), report connected date.
4. Disconnect the VoIP call, and submit the end-call action when the call is disconnected:
- (void)callDisconnected {
[self performEndCallActionWithUUID:self.call.uuid];
}
- (void)performEndCallActionWithUUID:(NSUUID *)uuid {
CXEndCallAction *endCallAction = [[CXEndCallAction alloc] initWithCallUUID:uuid];
CXTransaction *transaction = [[CXTransaction alloc] initWithAction:endCallAction];
[self.callKitCallController requestTransaction:transaction completion:^(NSError *error) {
if (error) {
NSLog(@"Failed to submit end-call transaction request: %@", error);
}
else {
NSLog(@"End-call transaction successfully done");
}
}];
}
Environments:
- Xcode9.4, Xcode10(GM)
- iPhone6s(12.0), iPhone8(11.4.1)
Best,
Bobie Chen