-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathAppDelegate.mm
173 lines (145 loc) · 8.34 KB
/
AppDelegate.mm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#import "AppDelegate.h"
#import <React/RCTBundleURLProvider.h>
#import <React/RCTLinkingManager.h>
@implementation AppDelegate
// Change to NO if you don't want debug alerts or logs.
BOOL isDebug = YES;
// Change to NO if you prefer to initialize and handle push tokens in the React Native layer
BOOL useNativeImplementation = YES;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.moduleName = @"KlaviyoReactNativeSdkExample";
self.initialProps = @{};
// iOS Installation Step 2: Set the UNUserNotificationCenter delegate to self
[UNUserNotificationCenter currentNotificationCenter].delegate = self;
if (useNativeImplementation) {
// iOS Installation Step 3: Initialize the SDK with public key, if initializing from native code
// Exclude if initializing from react native layer
[PushNotificationsHelper initializeSDK: @"YOUR_KLAVIYO_PUBLIC_API_KEY"];
// iOS Installation Step 4: Request notification permission from the user
// Exclude if handling permissions from react native layer
[PushNotificationsHelper requestNotificationPermission];
} else {
// Initialize cross-platform push library, e.g. Firebase
}
// refer to installation step 16 below
NSMutableDictionary * launchOptionsWithURL = [self getLaunchOptionsWithURL:launchOptions];
return [super application:application didFinishLaunchingWithOptions:launchOptionsWithURL];
}
// iOS Installation Step 6: Implement this delegate to receive and set the push token
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
if (useNativeImplementation) {
// iOS Installation Step 7: set the push token to Klaviyo SDK
// Exclude if handling push tokens from react native layer
[PushNotificationsHelper setPushTokenWithToken:deviceToken];
} else {
// Provide token to cross-platform push library, e.g. firebase
}
if (isDebug) {
NSString *token = [self stringFromDeviceToken:deviceToken];
NSLog(@"Device Token: %@", token);
}
}
// iOS Installation Step 8: [Optional] Implement this if registering with APNs fails
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
if (isDebug) {
NSLog(@"Failed to register for remote notifications: %@", error);
}
}
// iOS Installation Step 9: Implement the delegate didReceiveNotificationResponse to response to user actions (tapping on push) push notifications
// when the app is in the background
// NOTE: this delegate will NOT be called if iOS Installation Step 2 is not done.
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {
// iOS Installation Step 10: call `handleReceivingPushWithResponse` method and pass in the below arguments.
// Note that handleReceivingPushWithResponse calls our SDK and is something that has to be implemented in your app as well.
// Further, if you want to intercept urls instead of them being routed to the system and system calling `application:openURL:options:` you can implement the `deepLinkHandler` below
[PushNotificationsHelper handleReceivingPushWithResponse:response completionHandler:completionHandler deepLinkHandler:^(NSURL * _Nonnull url) {
NSLog(@"URL is %@", url);
[RCTLinkingManager application:UIApplication.sharedApplication openURL: url options: @{}];
}];
// iOS Installation Step 9a: update the app count to current badge number - 1. You can also set this to 0 if you
// no longer want the badge to show.
[PushNotificationsHelper updateBadgeCount: [UIApplication sharedApplication].applicationIconBadgeNumber - 1];
if (isDebug) {
UIAlertController *alert = [UIAlertController
alertControllerWithTitle:@"Push Notification"
message:@"handled background notifications"
preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction
actionWithTitle:@"OK"
style:UIAlertActionStyleDefault
handler:nil]];
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
}
}
// iOS Installation Step 11: Implement the delegate willPresentNotification to handle push notifications when the app is in the foreground
// NOTE: this delegate will NOT be called if iOS Installation Step 2 is not done.
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler {
if (isDebug) {
NSDictionary *userInfo = notification.request.content.userInfo;
// Handle the push notification payload as needed
NSLog(@"Received Push Notification: %@", userInfo);
// Example: Display an alert with the notification message
NSString *message = userInfo[@"aps"][@"alert"][@"body"];
UIAlertController *alert = [UIAlertController
alertControllerWithTitle:@"Push Notification"
message:message
preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
}
// iOS Installation Step 12: call the completion handler with presentation options here, such as showing a banner or playing a sound.
completionHandler(UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge | UNNotificationPresentationOptionSound);
}
// iOS Installation Step 13: Implement this method to receive deep link. There are some addition setup steps needed as mentioned in the readme here -
// https://github.com/klaviyo/klaviyo-swift-sdk?tab=readme-ov-file#deep-linking
// Calling `RCTLinkingManager` is required for your react native listeners to be called
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
return [RCTLinkingManager application:app openURL:url options:options];
}
// iOS Installation Step 14: if you want to reset the app badge count whenever the app becomes active implement this
// delegate method and set the badge count to 0. Note that this may sometimes mean that the user would miss the
// notification.
- (void)applicationDidBecomeActive:(UIApplication *)application {
[PushNotificationsHelper updateBadgeCount:0];
}
// iOS Installation Step 16: call this method from `application:didFinishLaunchingWithOptions:` before calling the super class method with
// the launch arguments. This is a workaround for a react issue where if the app is terminated the deep link isn't sent to the react native layer
// when it is coming from a remote notification.
// https://github.com/facebook/react-native/issues/32350
- (NSMutableDictionary *)getLaunchOptionsWithURL:(NSDictionary * _Nullable)launchOptions {
NSMutableDictionary *launchOptionsWithURL = [NSMutableDictionary dictionaryWithDictionary:launchOptions];
if (launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]) {
NSDictionary *remoteNotification = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];
if (remoteNotification[@"url"]) {
NSString *initialURL = remoteNotification[@"url"];
if (!launchOptions[UIApplicationLaunchOptionsURLKey]) {
launchOptionsWithURL[UIApplicationLaunchOptionsURLKey] = [NSURL URLWithString:initialURL];
}
}
}
return launchOptionsWithURL;
}
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
return [self bundleURL];
}
- (NSURL *)bundleURL
{
#if DEBUG
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
#else
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}
- (NSString *)stringFromDeviceToken:(NSData *)deviceToken {
const unsigned char *tokenBytes = (const unsigned char *)[deviceToken bytes];
NSMutableString *token = [NSMutableString stringWithCapacity:([deviceToken length] * 2)];
for (NSUInteger i = 0; i < [deviceToken length]; i++) {
[token appendFormat:@"%02x", tokenBytes[i]];
}
return token;
}
@end