From e7ed8d60bb3c29c2c549c271d175ac43938f3d2e Mon Sep 17 00:00:00 2001 From: Danmei Chen Date: Thu, 5 Mar 2020 16:21:41 +0100 Subject: [PATCH] fix display imcoming call repeatedly --- Classes/CallManager.swift | 18 +++++++++++ Classes/LinphoneAppDelegate.h | 1 + Classes/LinphoneAppDelegate.m | 59 ++++++++++++++++++++++++++-------- Classes/LinphoneManager.m | 1 - Classes/ProviderDelegate.swift | 9 ++++++ 5 files changed, 74 insertions(+), 14 deletions(-) diff --git a/Classes/CallManager.swift b/Classes/CallManager.swift index 4f03282bd..3195f6ce4 100644 --- a/Classes/CallManager.swift +++ b/Classes/CallManager.swift @@ -113,6 +113,15 @@ import AVFoundation return false } + @objc static func incomingCallMustBeDisplayed() -> Bool { + if #available(iOS 13.0, *) { + if UIApplication.shared.applicationState == .background && CallManager.callKitEnabled() { + return true + } + } + return false + } + @objc func allowSpeaker() -> Bool { if (UIDevice.current.userInterfaceIdiom == .pad) { // For now, ipad support only speaker. @@ -161,6 +170,15 @@ import AVFoundation displayIncomingCall(call: nil, handle: "Calling", hasVideo: false, callId: callId) } + // There is an error before display an incoming call. Attention, it's unnormal in this case! + @objc func displayForkIncomingCall() { + if CallManager.incomingCallMustBeDisplayed() { + // Display the call in any way, otherwise it will cause a crash. + Log.directLog(BCTBX_LOG_ERROR, text: "CallKit: please check the pushkit notification, there must be something wrong!") + providerDelegate.reportForkIncomingCall(); + } + } + func displayIncomingCall(call:Call?, handle: String, hasVideo: Bool, callId: String) { let uuid = UUID() let callInfo = CallInfo.newIncomingCallInfo(callId: callId) diff --git a/Classes/LinphoneAppDelegate.h b/Classes/LinphoneAppDelegate.h index 9728720cd..76815a31e 100644 --- a/Classes/LinphoneAppDelegate.h +++ b/Classes/LinphoneAppDelegate.h @@ -36,6 +36,7 @@ - (void)registerForNotifications; +@property (atomic, strong) NSString *callIdTraitedInBackGround; @property (nonatomic, retain) UIAlertController *waitingIndicator; @property (nonatomic, retain) NSString *configURL; @property (nonatomic, strong) UIWindow* window; diff --git a/Classes/LinphoneAppDelegate.m b/Classes/LinphoneAppDelegate.m index 0fbad7fcd..80a2f8000 100644 --- a/Classes/LinphoneAppDelegate.m +++ b/Classes/LinphoneAppDelegate.m @@ -46,6 +46,7 @@ self = [super init]; if (self != nil) { startedInBackground = FALSE; + _callIdTraitedInBackGround = @""; } _alreadyRegisteredForNotification = false; _onlyPortrait = FALSE; @@ -58,6 +59,7 @@ - (void)applicationDidEnterBackground:(UIApplication *)application { LOGI(@"%@", NSStringFromSelector(_cmd)); [LinphoneManager.instance enterBackgroundMode]; + _callIdTraitedInBackGround = @""; } - (void)applicationWillResignActive:(UIApplication *)application { @@ -427,33 +429,58 @@ } } -- (void)processRemoteNotification:(NSDictionary *)userInfo { - if (linphone_core_get_calls(LC)) { - // if there are calls, obviously our TCP socket shall be working - LOGD(@"Notification [%p] has no need to be processed because there already is an active call.", userInfo); - return; - } +-(void)displayfailedcall { + +} +- (void)processRemoteNotification:(NSDictionary *)userInfo { + // TODO: it works only for calls. NSDictionary *aps = [userInfo objectForKey:@"aps"]; if (!aps) { LOGE(@"Notification [%p] was empy, it's impossible to process it.", userInfo); + [CallManager.instance displayForkIncomingCall]; return; } NSString *loc_key = [aps objectForKey:@"loc-key"] ?: [[aps objectForKey:@"alert"] objectForKey:@"loc-key"]; if (!loc_key) { LOGE(@"Notification [%p] has no loc_key, it's impossible to process it.", userInfo); + [CallManager.instance displayForkIncomingCall]; return; } - + NSString *callId = [aps objectForKey:@"call-id"] ?: @""; - if (![callId isEqualToString:@""] && [loc_key isEqualToString:@"IC_MSG"] && [CallManager callKitEnabled]) { - // Report a new Incoming call without lantacy when the callkit is enabled. - if ([UIApplication sharedApplication].applicationState != UIApplicationStateActive && [self addLongTaskIDforCallID:callId]) { - [LinphoneManager.instance startPushLongRunningTask:loc_key callId:callId]; + if ([callId isEqualToString:@""]) { + [CallManager.instance displayForkIncomingCall]; + } + if (![loc_key isEqualToString:@"IC_MSG"]) { + [CallManager.instance displayForkIncomingCall]; + } + + if([CallManager incomingCallMustBeDisplayed]) { + // Since ios13, a new Incoming call must be displayed when the callkit is enabled and app is in background. + // Otherwise it will cause a crash. + if ([_callIdTraitedInBackGround isEqualToString:callId]) { + LOGD(@"Notification has traited (Background)."); + } else { + _callIdTraitedInBackGround = callId; + if ([UIApplication sharedApplication].applicationState != UIApplicationStateActive && [self addLongTaskIDforCallID:callId]) { + [LinphoneManager.instance startPushLongRunningTask:loc_key callId:callId]; + } + [LinphoneManager.instance addPushCallId:callId]; + [CallManager.instance displayIncomingCallWithCallId:callId]; + } + } else { + if (linphone_core_get_calls(LC)) { + // if there are calls, obviously our TCP socket shall be working + LOGD(@"Notification [%p] has no need to be processed because there already is an active call.", userInfo); + return; + } + + if ([_callIdTraitedInBackGround isEqualToString:callId]) { + LOGD(@"Notification has traited (Foreground)."); + return; } - [LinphoneManager.instance addPushCallId:callId]; - } else { NSString *uuid = [NSString stringWithFormat:@"", [LinphoneManager.instance lpConfigStringForKey:@"uuid" inSection:@"misc" withDefault:NULL]]; NSString *sipInstance = [aps objectForKey:@"uuid"]; if (sipInstance && uuid && ![sipInstance isEqualToString:uuid]) { @@ -487,6 +514,12 @@ notification.alertTitle = @"APN Pusher"; [[UIApplication sharedApplication] presentLocalNotificationNow:notification]; } + } else if (![callId isEqualToString:@""] && [loc_key isEqualToString:@"IC_MSG"] && [CallManager callKitEnabled]) { + // Report a new Incoming call when app is in foreground. + if ([UIApplication sharedApplication].applicationState != UIApplicationStateActive && [self addLongTaskIDforCallID:callId]) { + [LinphoneManager.instance startPushLongRunningTask:loc_key callId:callId]; + } + [LinphoneManager.instance addPushCallId:callId]; } } diff --git a/Classes/LinphoneManager.m b/Classes/LinphoneManager.m index 30a4651fa..9966f70af 100644 --- a/Classes/LinphoneManager.m +++ b/Classes/LinphoneManager.m @@ -1558,7 +1558,6 @@ static int comp_call_id(const LinphoneCall *call, const char *callid) { [pushCallIDs removeObjectAtIndex:0]; [pushCallIDs addObject:callid]; - [CallManager.instance displayIncomingCallWithCallId:callid]; } - (BOOL)popPushCallID:(NSString *)callId { diff --git a/Classes/ProviderDelegate.swift b/Classes/ProviderDelegate.swift index c63af6508..770535ac6 100644 --- a/Classes/ProviderDelegate.swift +++ b/Classes/ProviderDelegate.swift @@ -104,6 +104,15 @@ class ProviderDelegate: NSObject { } } } + + func reportForkIncomingCall() { + let uuid = UUID() + let update = CXCallUpdate() + update.remoteHandle = CXHandle(type:.generic, value: "Unknow") + + provider.reportNewIncomingCall(with: uuid, update: update, completion: {_ in}) + provider.reportCall(with: uuid, endedAt: .init(), reason: .failed) + } func updateCall(uuid: UUID, handle: String, hasVideo: Bool = false) { let update = CXCallUpdate()