mirror of
https://github.com/vector-im/element-ios.git
synced 2024-09-29 07:42:40 +00:00
Merge pull request #4424 from vector-im/element_4269_additions
VoIP: Fixes for PushKit Crashes
This commit is contained in:
commit
47355c0aa8
3 changed files with 73 additions and 65 deletions
|
@ -16,6 +16,8 @@ Changes to be released in next version
|
|||
* RoomDirectCallStatusBubbleCell: Fix crash when entering a DM after a call is hung-up/rejected while being answered (#4403).
|
||||
* ContactsDataSource: iPad Crashes when you select a contact in search and then collapse a section or clear the query text (#4414).
|
||||
* SettingsViewController: Fix "auto" theme message to clarify that it matches the system theme on iOS 13+ (#2860).
|
||||
* VoIP: Handle application inactive state too for VoIP pushes (#4269).
|
||||
* VoIP: Do not terminate the app if protected data not available (#4419).
|
||||
|
||||
⚠️ API Changes
|
||||
*
|
||||
|
|
|
@ -178,16 +178,17 @@ Matrix session observer used to detect new opened sessions.
|
|||
{
|
||||
[[UNUserNotificationCenter currentNotificationCenter] removeUnwantedNotifications];
|
||||
[[UNUserNotificationCenter currentNotificationCenter] removeCallNotificationsFor:nil];
|
||||
}
|
||||
|
||||
- (void)applicationDidEnterBackground
|
||||
{
|
||||
if (_pushNotificationStore.pushKitToken)
|
||||
{
|
||||
self.shouldReceiveVoIPPushes = YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)applicationDidEnterBackground
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
- (void)applicationDidBecomeActive
|
||||
{
|
||||
[[UNUserNotificationCenter currentNotificationCenter] removeUnwantedNotifications];
|
||||
|
@ -227,6 +228,8 @@ Matrix session observer used to detect new opened sessions.
|
|||
{
|
||||
_shouldReceiveVoIPPushes = shouldReceiveVoIPPushes;
|
||||
|
||||
MXLogDebug(@"[PushNotificationService] setShouldReceiveVoIPPushes: %u", _shouldReceiveVoIPPushes)
|
||||
|
||||
if (_shouldReceiveVoIPPushes && _pushNotificationStore.pushKitToken)
|
||||
{
|
||||
MXSession *session = [AppDelegate theDelegate].mxSessions.firstObject;
|
||||
|
@ -256,16 +259,25 @@ Matrix session observer used to detect new opened sessions.
|
|||
}
|
||||
else
|
||||
{
|
||||
_pushRegistry.delegate = nil;
|
||||
[self deconfigurePushKit];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)configurePushKit
|
||||
{
|
||||
MXLogDebug(@"[PushNotificationService] configurePushKit")
|
||||
|
||||
_pushRegistry.delegate = self;
|
||||
_pushRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];
|
||||
}
|
||||
|
||||
- (void)deconfigurePushKit
|
||||
{
|
||||
MXLogDebug(@"[PushNotificationService] deconfigurePushKit")
|
||||
|
||||
_pushRegistry.delegate = nil;
|
||||
}
|
||||
|
||||
- (void)removePusher:(MXPusher*)pusher inSession:(MXSession*)session
|
||||
{
|
||||
MXLogDebug(@"[PushNotificationService][Push] removePusher: %@", pusher.appId);
|
||||
|
@ -547,83 +559,83 @@ Matrix session observer used to detect new opened sessions.
|
|||
[[UNUserNotificationCenter currentNotificationCenter] removeUnwantedNotifications];
|
||||
[[UNUserNotificationCenter currentNotificationCenter] removeCallNotificationsFor:roomId];
|
||||
|
||||
if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground)
|
||||
if (@available(iOS 13.0, *))
|
||||
{
|
||||
MXLogDebug(@"[PushNotificationService] didReceiveIncomingPushWithPayload: application is in bg");
|
||||
// for iOS 13, we'll just report the incoming call in the same runloop. It means we cannot call an async API here.
|
||||
MXEvent *callInvite = [_pushNotificationStore callInviteForEventId:eventId];
|
||||
// remove event
|
||||
[_pushNotificationStore removeCallInviteWithEventId:eventId];
|
||||
MXSession *session = [AppDelegate theDelegate].mxSessions.firstObject;
|
||||
// when we have a VoIP push while the application is killed, session.callManager will not be ready yet. Configure it.
|
||||
[[AppDelegate theDelegate] configureCallManagerIfRequiredForSession:session];
|
||||
|
||||
if (@available(iOS 13.0, *))
|
||||
MXLogDebug(@"[PushNotificationService] didReceiveIncomingPushWithPayload: iOS 13+, callInvite: %@", callInvite);
|
||||
|
||||
if (callInvite)
|
||||
{
|
||||
// for iOS 13, we'll just report the incoming call in the same runloop. It means we cannot call an async API here.
|
||||
MXEvent *callInvite = [_pushNotificationStore callInviteForEventId:eventId];
|
||||
// remove event
|
||||
[_pushNotificationStore removeCallInviteWithEventId:eventId];
|
||||
MXSession *session = [AppDelegate theDelegate].mxSessions.firstObject;
|
||||
// when we have a VoIP push while the application is killed, session.callManager will not be ready yet. Configure it.
|
||||
[[AppDelegate theDelegate] configureCallManagerIfRequiredForSession:session];
|
||||
// We're using this dispatch_group to continue event stream after cache fully processed.
|
||||
dispatch_group_t dispatchGroup = dispatch_group_create();
|
||||
|
||||
MXLogDebug(@"[PushNotificationService] didReceiveIncomingPushWithPayload: callInvite: %@", callInvite);
|
||||
dispatch_group_enter(dispatchGroup);
|
||||
// Not continuing in completion block here, because PushKit mandates reporting a new call in the same run loop.
|
||||
// 'handleBackgroundSyncCacheIfRequiredWithCompletion' is processing to-device events synchronously.
|
||||
[session handleBackgroundSyncCacheIfRequiredWithCompletion:^{
|
||||
dispatch_group_leave(dispatchGroup);
|
||||
}];
|
||||
|
||||
if (callInvite)
|
||||
if (callInvite.eventType == MXEventTypeCallInvite)
|
||||
{
|
||||
// We're using this dispatch_group to continue event stream after cache fully processed.
|
||||
dispatch_group_t dispatchGroup = dispatch_group_create();
|
||||
|
||||
dispatch_group_enter(dispatchGroup);
|
||||
// Not continuing in completion block here, because PushKit mandates reporting a new call in the same run loop.
|
||||
// 'handleBackgroundSyncCacheIfRequiredWithCompletion' is processing to-device events synchronously.
|
||||
[session handleBackgroundSyncCacheIfRequiredWithCompletion:^{
|
||||
dispatch_group_leave(dispatchGroup);
|
||||
}];
|
||||
|
||||
if (callInvite.eventType == MXEventTypeCallInvite)
|
||||
// process the call invite synchronously
|
||||
[session.callManager handleCallEvent:callInvite];
|
||||
MXCallInviteEventContent *content = [MXCallInviteEventContent modelFromJSON:callInvite.content];
|
||||
MXCall *call = [session.callManager callWithCallId:content.callId];
|
||||
if (call)
|
||||
{
|
||||
// process the call invite synchronously
|
||||
[session.callManager handleCallEvent:callInvite];
|
||||
MXCallInviteEventContent *content = [MXCallInviteEventContent modelFromJSON:callInvite.content];
|
||||
MXCall *call = [session.callManager callWithCallId:content.callId];
|
||||
if (call)
|
||||
{
|
||||
[session.callManager.callKitAdapter reportIncomingCall:call];
|
||||
MXLogDebug(@"[PushNotificationService] didReceiveIncomingPushWithPayload: Reporting new call in room %@ for the event: %@", roomId, eventId);
|
||||
|
||||
// Wait for the sync response in cache to be processed for data integrity.
|
||||
dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^{
|
||||
// After reporting the call, we can continue async. Launch a background sync to handle call answers/declines on other devices of the user.
|
||||
[self launchBackgroundSync];
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
MXLogDebug(@"[PushNotificationService] didReceiveIncomingPushWithPayload: Error on call object on room %@ for the event: %@", roomId, eventId);
|
||||
}
|
||||
}
|
||||
else if ([callInvite.type isEqualToString:kWidgetMatrixEventTypeString] ||
|
||||
[callInvite.type isEqualToString:kWidgetModularEventTypeString])
|
||||
{
|
||||
[[AppDelegate theDelegate].callPresenter processWidgetEvent:callInvite
|
||||
inSession:session];
|
||||
[session.callManager.callKitAdapter reportIncomingCall:call];
|
||||
MXLogDebug(@"[PushNotificationService] didReceiveIncomingPushWithPayload: Reporting new call in room %@ for the event: %@", roomId, eventId);
|
||||
|
||||
// Wait for the sync response in cache to be processed for data integrity.
|
||||
dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^{
|
||||
// After reporting the call, we can continue async. Launch a background sync to handle call answers/declines on other devices of the user.
|
||||
[self launchBackgroundSync];
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// It's a serious error. There is nothing to avoid iOS to kill us here.
|
||||
MXLogDebug(@"[PushNotificationService] didReceiveIncomingPushWithPayload: We have an unknown type of event for %@. There is something wrong.", eventId);
|
||||
MXLogDebug(@"[PushNotificationService] didReceiveIncomingPushWithPayload: Error on call object on room %@ for the event: %@", roomId, eventId);
|
||||
}
|
||||
}
|
||||
else if ([callInvite.type isEqualToString:kWidgetMatrixEventTypeString] ||
|
||||
[callInvite.type isEqualToString:kWidgetModularEventTypeString])
|
||||
{
|
||||
[[AppDelegate theDelegate].callPresenter processWidgetEvent:callInvite
|
||||
inSession:session];
|
||||
}
|
||||
else
|
||||
{
|
||||
// It's a serious error. There is nothing to avoid iOS to kill us here.
|
||||
MXLogDebug(@"[PushNotificationService] didReceiveIncomingPushWithPayload: iOS 13 and in bg, but we don't have the callInvite event for the eventId: %@. There is something wrong.", eventId);
|
||||
MXLogDebug(@"[PushNotificationService] didReceiveIncomingPushWithPayload: We have an unknown type of event for %@. There is something wrong.", eventId);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// below iOS 13, we can call an async API. After background sync, we'll hopefully fetch the call invite and report a new call to the CallKit.
|
||||
[self launchBackgroundSync];
|
||||
// It's a serious error. There is nothing to avoid iOS to kill us here.
|
||||
MXLogDebug(@"[PushNotificationService] didReceiveIncomingPushWithPayload: iOS 13+, but we don't have the callInvite event for the eventId: %@.", eventId);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MXLogDebug(@"[PushNotificationService] didReceiveIncomingPushWithPayload: application is not in bg. There is something wrong.");
|
||||
if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive)
|
||||
{
|
||||
// below iOS 13, we don't have to report a call immediately.
|
||||
// We can wait for a call invite from event stream and process.
|
||||
MXLogDebug(@"[PushNotificationService] didReceiveIncomingPushWithPayload: Below iOS 13 and active app. Do nothing.");
|
||||
completion();
|
||||
return;
|
||||
}
|
||||
|
||||
// below iOS 13, we can call an async API. After background sync, we'll hopefully fetch the call invite and report a new call to the CallKit.
|
||||
[self launchBackgroundSync];
|
||||
}
|
||||
|
||||
completion();
|
||||
|
|
|
@ -369,12 +369,6 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
|
|||
|
||||
MXLogDebug(@"[AppDelegate] didFinishLaunchingWithOptions: isProtectedDataAvailable: %@", @([application isProtectedDataAvailable]));
|
||||
|
||||
if (![application isProtectedDataAvailable])
|
||||
{
|
||||
MXLogDebug(@"[AppDelegate] didFinishLaunchingWithOptions: Terminating the app because protected data not available");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
_configuration = [AppConfiguration new];
|
||||
|
||||
self.appInfo = AppInfo.current;
|
||||
|
|
Loading…
Reference in a new issue