Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Notification conversion #382

Open
wants to merge 40 commits into
base: master
Choose a base branch
from

Conversation

KennyHuRadar
Copy link
Contributor

@KennyHuRadar KennyHuRadar commented Aug 16, 2024

We are creating 3 new events:

  • opened_radar_notification: when user opens the app via tapping on notification generated by the Radar SDK
  • opened_notification: when user opens the app by tapping on other notifications from the app
  • delivered_on_premise_notification: when our SDK detects on premise notification getting delivered

delivered_on_premise_notification may be noticed by our SDK and called when:

  • didEnterRegion is fired via the OS (real time receipt but requires background)
  • when background task fires (technically may be as frequent as once an hour, but in practice may be once or twice a day)
  • when the user next opens the app

image

QA that background processing works:
image

image

@KennyHuRadar KennyHuRadar marked this pull request as ready for review August 21, 2024 18:06
}

+ (void)checkForSentOnPremiseNotifications {
// check if there any pending notifications that have been sent, we will only be doing this if the app is not been opened by a notification
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

old

+ (void)scheduleBackgroundNotificationChecks {
if (@available(iOS 13.0, *)) {
BGAppRefreshTaskRequest *request = [[BGAppRefreshTaskRequest alloc] initWithIdentifier:@"io.radar.notificationCheck"];
request.earliestBeginDate = [NSDate dateWithTimeIntervalSinceNow:60];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's schedule this for an hour?

@KennyHuRadar KennyHuRadar changed the title [WIP] notification conversion Notification conversion Aug 27, 2024
[RadarState clearPendingNotificationRequests];

// Call the original method (which is now swizzled)
[self swizzled_userNotificationCenter:center didReceiveNotificationResponse:response withCompletionHandler:completionHandler];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have firsthand experience with swizzling, but this looks like a recursive call, which if it were, wouldn't be right. What's going on here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since we swizzled the methods, [[self swizzled_userNotificationCenter:center didReceiveNotificationResponse:response withCompletionHandler:completionHandler];] now links to the UNUserNotificationCenter

Comment on lines 118 to 119
// do we still want to log the normal app open event?
[RadarSettings updateLastAppOpenTime];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to self to check this against the opened_app logic.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah this is right, since we are now having the open notification be a form of the opened_app event, we do not want to call the code inside logOpenedAppConversion


+ (void)addOnPremiseNotificationRequests:(NSArray<UNNotificationRequest *> *)requests {
UNUserNotificationCenter *notificationCenter = [UNUserNotificationCenter currentNotificationCenter];
[notificationCenter getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings *settings) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use this to grab the authorization status and stash it in state as well

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that this its probably something we want to do and send up like we do send up location authorization.
However this is slightly off tangent to this PR and requires some server work as well, should we do this in another PR?

Comment on lines +210 to +212
if (error) {
[[RadarLogger sharedInstance] logWithLevel:RadarLogLevelError message:[NSString stringWithFormat:@"Error scheduling app refresh task: %@", error]];
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seeing the following in Waypoint:

Error scheduling app refresh task: Error Domain=BGTaskSchedulerErrorDomain Code=3 "(null)"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We get this when we try and schedule on the simulator.

@KennyHuRadar
Copy link
Contributor Author

per offline discussion, we want to get notification permissions and just store it in RadarState for now.

@KennyHuRadar
Copy link
Contributor Author

Comment on lines 125 to 147
+ (void)checkForSentOnPremiseNotifications {
NSArray<UNNotificationRequest *> *registeredNotifications = [RadarState pendingNotificationRequests];
if (NSClassFromString(@"XCTestCase") == nil) {
[[UNUserNotificationCenter currentNotificationCenter] getPendingNotificationRequestsWithCompletionHandler:^(NSArray<UNNotificationRequest *> *_Nonnull requests) {
NSMutableSet *pendingIdentifiers = [NSMutableSet new];

for (UNNotificationRequest *request in requests) {
[pendingIdentifiers addObject:request.identifier];
}

for (UNNotificationRequest *request in registeredNotifications) {
if (![pendingIdentifiers containsObject:request.identifier]) {
[[RadarLogger sharedInstance] logWithLevel:RadarLogLevelDebug message:[NSString stringWithFormat:@"Found pending notification | identifier = %@", request]];
NSDate *lastCheckedTime = [RadarState lastCheckedOnPremiseNotification];
[Radar logConversionWithNotification:request eventName:@"delivered_on_premise_notification" conversionSource:nil deliveredAfter:lastCheckedTime];
// prevent double counting of the same notification
[RadarState removePendingNotificationRequest:request];
}
}
}];
}
[RadarState lastCheckedOnPremiseNotification];
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add some RadarLogger logs to this

NSMutableArray *identifiers = [NSMutableArray new];
for (UNNotificationRequest *request in requests) {
if ([request.identifier hasPrefix:kSyncGeofenceIdentifierPrefix]) {
[[RadarLogger sharedInstance] logWithLevel:RadarLogLevelInfo message:[NSString stringWithFormat:@"Found pending notification | identifier = %@", request.identifier]];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's say "Found pending notification to remove |..."

Comment on lines 589 to 594
[RadarNotificationHelper checkForSentOnPremiseNotifications];

[RadarState clearPendingNotificationRequests];

[RadarNotificationHelper removePendingNotificationsWithCompletionHandler: ^{
[RadarNotificationHelper addOnPremiseNotificationRequests:requests];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possible race? Do we need to call removePendingNotificationsWithCompletionHandler in a completion handler of clearPendingNotificationRequests (which itself maybe is called in a completion handler of checkForSentOnPremiseNotifications)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we do indeed need a completion handler for checkForSentOnPremiseNotifications but not for clearPendingNotificationRequests since it does not step on the other calls.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants