diff --git a/Classes/LinphoneAppDelegate.m b/Classes/LinphoneAppDelegate.m index a43af202f..a45cf9f92 100644 --- a/Classes/LinphoneAppDelegate.m +++ b/Classes/LinphoneAppDelegate.m @@ -421,8 +421,9 @@ if (aps != nil) { NSDictionary *alert = [aps objectForKey:@"alert"]; + NSString *loc_key = [aps objectForKey:@"loc-key"]; if (alert != nil) { - NSString *loc_key = [alert objectForKey:@"loc-key"]; + loc_key = [alert objectForKey:@"loc-key"]; /*if we receive a remote notification, it is probably because our TCP background socket was no more working. As a result, break it and refresh registers in order to make sure to receive incoming INVITE or MESSAGE*/ if (linphone_core_get_calls(LC) == NULL) { // if there are calls, obviously our TCP socket shall be working @@ -463,13 +464,17 @@ } else if ([callId isEqual: @""]) { LOGE(@"PushNotification: does not have call-id yet, fix it !"); } - - if ([loc_key isEqualToString:@"IC_MSG"]) { - [self fixRing]; - } } } } + if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground && loc_key) { + if ([loc_key isEqualToString:@"IC_MSG"]) { + [LinphoneManager.instance startPushLongRunningTask:FALSE]; + [self fixRing]; + } else if ([loc_key isEqualToString:@"IM_MSG"]) { + [LinphoneManager.instance startPushLongRunningTask:TRUE]; + } + } } LOGI(@"Notification %@ processed", userInfo.description); } @@ -669,11 +674,13 @@ didInvalidatePushTokenForType:(NSString *)type { } - (void)pushRegistry:(PKPushRegistry *)registry - didUpdatePushCredentials:(PKPushCredentials *)credentials - forType:(NSString *)type { - LOGI(@"PushKit credentials updated"); - LOGI(@"voip token: %@", (credentials.token)); - dispatch_async(dispatch_get_main_queue(), ^{[LinphoneManager.instance setPushNotificationToken:credentials.token];}); + didUpdatePushCredentials:(PKPushCredentials *)credentials + forType:(PKPushType)type { + LOGI(@"PushKit credentials updated"); + LOGI(@"voip token: %@", (credentials.token)); + dispatch_async(dispatch_get_main_queue(), ^{ + [LinphoneManager.instance setPushNotificationToken:credentials.token]; + }); } #pragma mark - UNUserNotifications Framework @@ -689,6 +696,9 @@ didReceiveNotificationResponse:(UNNotificationResponse *)response LOGD(response.description); NSString *callId = (NSString *)[response.notification.request.content.userInfo objectForKey:@"CallId"]; + if (!callId) { + return; + } LinphoneCall *call = [LinphoneManager.instance callByCallId:callId]; if (call) { LinphoneCallAppData *data = (__bridge LinphoneCallAppData *)linphone_call_get_user_data(call); diff --git a/Classes/LinphoneManager.h b/Classes/LinphoneManager.h index d619c6939..b431d87f8 100644 --- a/Classes/LinphoneManager.h +++ b/Classes/LinphoneManager.h @@ -109,6 +109,7 @@ typedef struct _LinphoneManagerSounds { Connectivity connectivity; UIBackgroundTaskIdentifier pausedCallBgTask; UIBackgroundTaskIdentifier incallBgTask; + UIBackgroundTaskIdentifier pushBgTask; CTCallCenter* mCallCenter; NSDate *mLastKeepAliveDate; @public @@ -141,7 +142,7 @@ typedef struct _LinphoneManagerSounds { - (LinphoneCall *)callByCallId:(NSString *)call_id; - (void)cancelLocalNotifTimerForCallId:(NSString*)callid; - (void)alertLIME:(LinphoneChatRoom *)room; - +- (void)startPushLongRunningTask:(BOOL)msg; + (BOOL)langageDirectionIsRTL; + (void)kickOffNetworkConnection; - (void)setupNetworkReachabilityCallback; diff --git a/Classes/LinphoneManager.m b/Classes/LinphoneManager.m index 62e2095fd..5c4f8efa6 100644 --- a/Classes/LinphoneManager.m +++ b/Classes/LinphoneManager.m @@ -662,6 +662,11 @@ static void linphone_iphone_display_status(struct _LinphoneCore *lc, const char NSString *address = [FastAddressBook displayNameForAddress:addr]; if (state == LinphoneCallIncomingReceived) { + if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) { + LOGI(@"Call received, stopping background task"); + [[UIApplication sharedApplication] endBackgroundTask:pushBgTask]; + pushBgTask = 0; + } LinphoneCallLog *callLog = linphone_call_get_call_log(call); NSString *callId = [NSString stringWithUTF8String:linphone_call_log_get_call_id(callLog)]; /*first step is to re-enable ctcall center*/ @@ -1166,7 +1171,6 @@ static void linphone_iphone_popup_password_request(LinphoneCore *lc, const char _silentPushCompletion = nil; } #pragma deploymate pop - NSString *callID = [NSString stringWithUTF8String:linphone_chat_message_get_custom_header(msg, "Call-ID")]; const LinphoneAddress *remoteAddress = linphone_chat_message_get_from_address(msg); NSString *from = [FastAddressBook displayNameForAddress:remoteAddress]; @@ -1177,57 +1181,63 @@ static void linphone_iphone_popup_password_request(LinphoneCore *lc, const char if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground || ((PhoneMainView.instance.currentView != ChatsListView.compositeViewDescription) && ((PhoneMainView.instance.currentView != ChatConversationView.compositeViewDescription))) || (PhoneMainView.instance.currentView == ChatConversationView.compositeViewDescription && room != PhoneMainView.instance.currentRoom)) { // Create a new notification - - if(floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_9_x_Max) { - NSArray *actions; - - if ([[UIDevice.currentDevice systemVersion] floatValue] < 9 || - [LinphoneManager.instance lpConfigBoolForKey:@"show_msg_in_notif"] == NO) { - - UIMutableUserNotificationAction *reply = [[UIMutableUserNotificationAction alloc] init]; - reply.identifier = @"reply"; - reply.title = NSLocalizedString(@"Reply", nil); - reply.activationMode = UIUserNotificationActivationModeForeground; - reply.destructive = NO; - reply.authenticationRequired = YES; - - UIMutableUserNotificationAction *mark_read = [[UIMutableUserNotificationAction alloc] init]; - mark_read.identifier = @"mark_read"; - mark_read.title = NSLocalizedString(@"Mark Read", nil); - mark_read.activationMode = UIUserNotificationActivationModeBackground; - mark_read.destructive = NO; - mark_read.authenticationRequired = NO; - - actions = @[ mark_read, reply ]; - } else { - // iOS 9 allows for inline reply. We don't propose mark_read in this case - UIMutableUserNotificationAction *reply_inline = [[UIMutableUserNotificationAction alloc] init]; - - reply_inline.identifier = @"reply_inline"; - reply_inline.title = NSLocalizedString(@"Reply", nil); - reply_inline.activationMode = UIUserNotificationActivationModeBackground; - reply_inline.destructive = NO; - reply_inline.authenticationRequired = NO; - reply_inline.behavior = UIUserNotificationActionBehaviorTextInput; - - actions = @[ reply_inline ]; - } - - UIMutableUserNotificationCategory *msgcat = [[UIMutableUserNotificationCategory alloc] init]; - msgcat.identifier = @"incoming_msg"; - [msgcat setActions:actions forContext:UIUserNotificationActionContextDefault]; - [msgcat setActions:actions forContext:UIUserNotificationActionContextMinimal]; - - NSSet* categories = [NSSet setWithObjects:msgcat, nil]; - - UIUserNotificationSettings *set = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound) categories:categories]; - [[UIApplication sharedApplication] registerUserNotificationSettings:set]; - - UILocalNotification *notif = [[UILocalNotification alloc] init]; - if (notif) { - NSString *chat = [UIChatBubbleTextCell TextMessageForChat:msg]; - notif.repeatInterval = 0; - if ([[UIDevice currentDevice].systemVersion floatValue] >= 8) { + LOGI(@"Message received, stopping background task"); + [[UIApplication sharedApplication] endBackgroundTask:pushBgTask]; + pushBgTask = 0; + + if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_9_x_Max) { + NSArray *actions; + + if ([[UIDevice.currentDevice systemVersion] floatValue] < 9 || + [LinphoneManager.instance lpConfigBoolForKey:@"show_msg_in_notif"] == NO) { + + UIMutableUserNotificationAction *reply = [[UIMutableUserNotificationAction alloc] init]; + reply.identifier = @"reply"; + reply.title = NSLocalizedString(@"Reply", nil); + reply.activationMode = UIUserNotificationActivationModeForeground; + reply.destructive = NO; + reply.authenticationRequired = YES; + + UIMutableUserNotificationAction *mark_read = [[UIMutableUserNotificationAction alloc] init]; + mark_read.identifier = @"mark_read"; + mark_read.title = NSLocalizedString(@"Mark Read", nil); + mark_read.activationMode = UIUserNotificationActivationModeBackground; + mark_read.destructive = NO; + mark_read.authenticationRequired = NO; + + actions = @[ mark_read, reply ]; + } else { + // iOS 9 allows for inline reply. We don't propose mark_read in this case + UIMutableUserNotificationAction *reply_inline = [[UIMutableUserNotificationAction alloc] init]; + + reply_inline.identifier = @"reply_inline"; + reply_inline.title = NSLocalizedString(@"Reply", nil); + reply_inline.activationMode = UIUserNotificationActivationModeBackground; + reply_inline.destructive = NO; + reply_inline.authenticationRequired = NO; + reply_inline.behavior = UIUserNotificationActionBehaviorTextInput; + + actions = @[ reply_inline ]; + } + + UIMutableUserNotificationCategory *msgcat = [[UIMutableUserNotificationCategory alloc] init]; + msgcat.identifier = @"incoming_msg"; + [msgcat setActions:actions forContext:UIUserNotificationActionContextDefault]; + [msgcat setActions:actions forContext:UIUserNotificationActionContextMinimal]; + + NSSet *categories = [NSSet setWithObjects:msgcat, nil]; + + UIUserNotificationSettings *set = + [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeAlert | + UIUserNotificationTypeBadge | UIUserNotificationTypeSound) + categories:categories]; + [[UIApplication sharedApplication] registerUserNotificationSettings:set]; + + UILocalNotification *notif = [[UILocalNotification alloc] init]; + if (notif) { + NSString *chat = [UIChatBubbleTextCell TextMessageForChat:msg]; + notif.repeatInterval = 0; + if ([[UIDevice currentDevice].systemVersion floatValue] >= 8) { #pragma deploymate push "ignored-api-availability" notif.category = @"incoming_msg"; #pragma deploymate pop @@ -2192,6 +2202,52 @@ static int comp_call_state_paused(const LinphoneCall *call, const void *param) { [[UIApplication sharedApplication] backgroundTimeRemaining]); } +- (void)startPushLongRunningTask:(BOOL)msg { + pushBgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ + if (msg) { + LOGW(@"Incomming message couldn't be received"); + UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init]; + content.title = NSLocalizedString(@"Message received", nil); + content.body = NSLocalizedString(@"You have received a message.", nil); + content.categoryIdentifier = @"push_msg"; + + UNNotificationRequest *req = + [UNNotificationRequest requestWithIdentifier:@"push_msg" content:content trigger:NULL]; + [[UNUserNotificationCenter currentNotificationCenter] + addNotificationRequest:req + withCompletionHandler:^(NSError *_Nullable error) { + // Enable or disable features based on authorization. + if (error) { + LOGD(@"Error while adding notification request :"); + LOGD(error.description); + } + }]; + } else { + LOGW(@"Incomming call couldn't be received"); + UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init]; + content.title = NSLocalizedString(@"Missed call", nil); + content.body = NSLocalizedString(@"You have missed a call.", nil); + content.categoryIdentifier = @"push_call"; + + UNNotificationRequest *req = + [UNNotificationRequest requestWithIdentifier:@"push_call" content:content trigger:NULL]; + [[UNUserNotificationCenter currentNotificationCenter] + addNotificationRequest:req + withCompletionHandler:^(NSError *_Nullable error) { + // Enable or disable features based on authorization. + if (error) { + LOGD(@"Error while adding notification request :"); + LOGD(error.description); + } + }]; + } + [[UIApplication sharedApplication] endBackgroundTask:pushBgTask]; + pushBgTask = 0; + }]; + LOGI(@"Long running task started, remaining [%g s] because a push has been received", + [[UIApplication sharedApplication] backgroundTimeRemaining]); +} + - (void)enableProxyPublish:(BOOL)enabled { if (linphone_core_get_global_state(LC) != LinphoneGlobalOn || !linphone_core_get_default_friend_list(LC)) { LOGW(@"Not changing presence configuration because linphone core not ready yet"); @@ -2217,7 +2273,9 @@ static int comp_call_state_paused(const LinphoneCall *call, const void *param) { linphone_core_iterate(theLinphoneCore); } - linphone_friend_list_enable_subscriptions(linphone_core_get_default_friend_list(LC), enabled); + linphone_friend_list_enable_subscriptions(linphone_core_get_default_friend_list(LC), + enabled && + [LinphoneManager.instance lpConfigBoolForKey:@"use_rls_presence"]); } - (BOOL)enterBackgroundMode {