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

test: update apn sample app with 3rd party SDK that handles push #225

Merged
merged 10 commits into from
Feb 12, 2024
25 changes: 9 additions & 16 deletions Apps/APN/ios/AppDelegate.mm
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#import <UserNotifications/UserNotifications.h>
#import <RNCPushNotificationIOS.h>
#import <React/RCTLinkingManager.h>
#import "RNNotifications.h"
levibostian marked this conversation as resolved.
Show resolved Hide resolved

#if RCT_NEW_ARCH_ENABLED
#import <React/CoreModulesPlugins.h>
Expand Down Expand Up @@ -76,7 +77,9 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];

[pnHandlerObj setupCustomerIOClickHandling:self];
[pnHandlerObj setupCustomerIOClickHandling];

[RNNotifications startMonitorNotifications];
levibostian marked this conversation as resolved.
Show resolved Hide resolved

return YES;
}
Expand Down Expand Up @@ -156,35 +159,25 @@ - (void)application:(UIApplication *)application didRegisterForRemoteNotificatio
{
// Register device to receive push notifications with device token
[pnHandlerObj application:application deviceToken:deviceToken];

[RNNotifications didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}

// Required for the notification event. You must call the completion handler after handling the remote notification.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
[RNCPushNotificationIOS didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];

[RNNotifications didReceiveBackgroundNotification:userInfo withCompletionHandler:completionHandler];
}

// Required for the registrationError event.
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
[pnHandlerObj application:application error:error];
}

// Required for localNotification event
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)(void))completionHandler
{
[pnHandlerObj userNotificationCenter:center didReceiveNotificationResponse:response withCompletionHandler:completionHandler];

[RNCPushNotificationIOS didReceiveNotificationResponse:response];
}

//Called when a notification is delivered to a foreground app.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
completionHandler(UNNotificationPresentationOptionSound | UNNotificationPresentationOptionList | UNNotificationPresentationOptionBanner | UNNotificationPresentationOptionBadge);
levibostian marked this conversation as resolved.
Show resolved Hide resolved
[RNNotifications didFailToRegisterForRemoteNotificationsWithError:error];
}

// Deep linking
Expand Down
21 changes: 3 additions & 18 deletions Apps/APN/ios/MyAppPushNotificationsHandler.swift
Original file line number Diff line number Diff line change
@@ -1,25 +1,22 @@
import Foundation
import CioMessagingPushAPN
import UserNotifications
import CioTracking

@objc
public class MyAppPushNotificationsHandler : NSObject {

public override init() {}

@objc(setupCustomerIOClickHandling:)
public func setupCustomerIOClickHandling(withNotificationDelegate notificationDelegate: UNUserNotificationCenterDelegate) {
@objc(setupCustomerIOClickHandling)
levibostian marked this conversation as resolved.
Show resolved Hide resolved
public func setupCustomerIOClickHandling() {
// This line of code is required in order for the Customer.io SDK to handle push notification click events.
// We are working on removing this requirement in a future release.
// Remember to modify the siteId and apiKey with your own values.
CustomerIO.initialize(siteId: Env.siteId, apiKey: Env.apiKey, region: .US) { config in
config.autoTrackDeviceAttributes = true
config.logLevel = .debug
}

let center = UNUserNotificationCenter.current()
center.delegate = notificationDelegate
MessagingPushAPN.initialize(configOptions: nil)
levibostian marked this conversation as resolved.
Show resolved Hide resolved
}

@objc(application:deviceToken:)
Expand All @@ -31,16 +28,4 @@ public class MyAppPushNotificationsHandler : NSObject {
public func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
MessagingPush.shared.application(application, didFailToRegisterForRemoteNotificationsWithError: error)
}

@objc(userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:)
public func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
let handled = MessagingPush.shared.userNotificationCenter(center, didReceive: response,
withCompletionHandler: completionHandler)

// If the Customer.io SDK does not handle the push, it's up to you to handle it and call the
// completion handler. If the SDK did handle it, it called the completion handler for you.
if !handled {
completionHandler()
}
}
}
1 change: 1 addition & 0 deletions Apps/APN/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"react-native": "0.72.4",
"react-native-device-info": "^10.7.0",
"react-native-gesture-handler": "^2.12.1",
"react-native-notifications": "^5.1.0",
"react-native-reanimated": "3.2.0",
"react-native-safe-area-context": "^4.2.5",
"react-native-screens": "~3.24.0",
Expand Down
42 changes: 42 additions & 0 deletions Apps/APN/src/screens/Dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import { useUserStateContext } from '../state/userState';
import { generateRandomNumber } from '../utils/helpers';
import { navigateToScreen } from '../utils/navigation';
import Prompts from '../utils/prompts';
import { Notifications } from 'react-native-notifications';
import { CustomerIO } from 'customerio-reactnative';

const pushPermissionAlertTitle = 'Push Permission';

Expand Down Expand Up @@ -138,6 +140,15 @@ const Dashboard = ({ navigation }) => {
handlePushPermissionCheck();
break;

case ActionItem.SHOW_LOCAL_PUSH:
// How we are able to test behavior of pushes sent by other SDKs, not CIO.
// Have 3rd party SDK create a push. We expect the SDK is able to handle this push that it owns.
Notifications.postLocalNotification({
body: 'Try clicking on me. The SDK that sent this should also be able to handle it.',
title: 'Local push not sent by Customer.io',
});
break;

case ActionItem.SIGN_OUT:
onUserStateChanged(null);
break;
Expand All @@ -150,6 +161,32 @@ const Dashboard = ({ navigation }) => {
}
};

// Setup 3rd party SDK, react-native-notifications
// We install this SDK into sample app to make sure the CIO SDK behaves as expected when there is another SDK installed that handles push notifications.
//
// Important to test that 3rd party SDK is able to decide if a push is shown or not while app is in foreground for non-CIO sent pushes.
Notifications.events().registerNotificationReceivedForeground(
(notification: Notification, completion) => {
console.log(
`Non-Customer.io notification received in foreground: ${notification.title} : ${notification.body}`
);

completion({ alert: true, sound: true, badge: true });
}
);
// Important to test that 3rd party SDK is able to receive a callback when a push notification is clicked for non-CIO sent pushes.
Notifications.events().registerNotificationOpened(
levibostian marked this conversation as resolved.
Show resolved Hide resolved
(notification: Notification, completion) => {
console.log(
`Non-Customer.io notification opened: ${notification.payload}`
);

CustomerIO.track('push clicked', { push: notification.payload });

completion();
}
);

return (
<View style={styles.container}>
<View style={styles.topBar}>
Expand Down Expand Up @@ -218,6 +255,11 @@ const ActionItem = {
contentDesc: 'Show Push Prompt Button',
targetScreen: null,
},
SHOW_LOCAL_PUSH: {
text: 'Show Local Push',
contentDesc: 'Show Local Push Button',
targetScreen: null,
},
SIGN_OUT: {
text: 'Log Out',
contentDesc: 'Log Out Button',
Expand Down
Loading