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
28 changes: 10 additions & 18 deletions Apps/APN/ios/MyAppPushNotificationsHandler.swift
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
import Foundation
import CioMessagingPushAPN
import UserNotifications
import CioTracking

/**
* This file was created based on the Customer.io React Native SDK documentation for setting up push notifications in your app.
*
* See the documentation to learn how to add this file to your app:
* https://customer.io/docs/sdk/react-native/push-notifications/push/#integrate-push-capabilities-in-your-app
*/

@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 +35,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()
}
}
}
86 changes: 46 additions & 40 deletions Apps/APN/ios/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,39 +1,39 @@
PODS:
- boost (1.76.0)
- customerio-reactnative (3.2.0):
- customerio-reactnative/nopush (= 3.2.0)
- CustomerIO/MessagingInApp (= 2.8.4)
- CustomerIO/Tracking (= 2.8.4)
- customerio-reactnative (3.4.0):
- customerio-reactnative/nopush (= 3.4.0)
- CustomerIO/MessagingInApp (= 2.11.0)
- CustomerIO/Tracking (= 2.11.0)
- React-Core
- customerio-reactnative-richpush/apn (3.2.0):
- CustomerIO/MessagingPushAPN (= 2.8.4)
- customerio-reactnative/apn (3.2.0):
- CustomerIO/MessagingInApp (= 2.8.4)
- CustomerIO/MessagingPushAPN (= 2.8.4)
- CustomerIO/Tracking (= 2.8.4)
- customerio-reactnative-richpush/apn (3.4.0):
- CustomerIO/MessagingPushAPN (= 2.11.0)
- customerio-reactnative/apn (3.4.0):
- CustomerIO/MessagingInApp (= 2.11.0)
- CustomerIO/MessagingPushAPN (= 2.11.0)
- CustomerIO/Tracking (= 2.11.0)
- React-Core
- customerio-reactnative/nopush (3.2.0):
- CustomerIO/MessagingInApp (= 2.8.4)
- CustomerIO/MessagingPush (= 2.8.4)
- CustomerIO/Tracking (= 2.8.4)
- customerio-reactnative/nopush (3.4.0):
- CustomerIO/MessagingInApp (= 2.11.0)
- CustomerIO/MessagingPush (= 2.11.0)
- CustomerIO/Tracking (= 2.11.0)
- React-Core
- CustomerIO/MessagingInApp (2.8.4):
- CustomerIOMessagingInApp (= 2.8.4)
- CustomerIO/MessagingPush (2.8.4):
- CustomerIOMessagingPush (= 2.8.4)
- CustomerIO/MessagingPushAPN (2.8.4):
- CustomerIOMessagingPushAPN (= 2.8.4)
- CustomerIO/Tracking (2.8.4):
- CustomerIOTracking (= 2.8.4)
- CustomerIOCommon (2.8.4)
- CustomerIOMessagingInApp (2.8.4):
- CustomerIOTracking (= 2.8.4)
- CustomerIOMessagingPush (2.8.4):
- CustomerIOTracking (= 2.8.4)
- CustomerIOMessagingPushAPN (2.8.4):
- CustomerIOMessagingPush (= 2.8.4)
- CustomerIOTracking (2.8.4):
- CustomerIOCommon (= 2.8.4)
- CustomerIO/MessagingInApp (2.11.0):
- CustomerIOMessagingInApp (= 2.11.0)
- CustomerIO/MessagingPush (2.11.0):
- CustomerIOMessagingPush (= 2.11.0)
- CustomerIO/MessagingPushAPN (2.11.0):
- CustomerIOMessagingPushAPN (= 2.11.0)
- CustomerIO/Tracking (2.11.0):
- CustomerIOTracking (= 2.11.0)
- CustomerIOCommon (2.11.0)
- CustomerIOMessagingInApp (2.11.0):
- CustomerIOTracking (= 2.11.0)
- CustomerIOMessagingPush (2.11.0):
- CustomerIOTracking (= 2.11.0)
- CustomerIOMessagingPushAPN (2.11.0):
- CustomerIOMessagingPush (= 2.11.0)
- CustomerIOTracking (2.11.0):
- CustomerIOCommon (= 2.11.0)
- DoubleConversion (1.1.6)
- FBLazyVector (0.72.4)
- FBReactNativeSpec (0.72.4):
Expand Down Expand Up @@ -349,6 +349,8 @@ PODS:
- React-jsinspector (0.72.4)
- React-logger (0.72.4):
- glog
- react-native-notifications (5.1.0):
- React-Core
- react-native-safe-area-context (4.7.1):
- React-Core
- React-NativeModulesApple (0.72.4):
Expand Down Expand Up @@ -532,6 +534,7 @@ DEPENDENCIES:
- React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`)
- React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`)
- React-logger (from `../node_modules/react-native/ReactCommon/logger`)
- react-native-notifications (from `../node_modules/react-native-notifications`)
- react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
- React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`)
- React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`)
Expand Down Expand Up @@ -620,6 +623,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/jsinspector"
React-logger:
:path: "../node_modules/react-native/ReactCommon/logger"
react-native-notifications:
:path: "../node_modules/react-native-notifications"
react-native-safe-area-context:
:path: "../node_modules/react-native-safe-area-context"
React-NativeModulesApple:
Expand Down Expand Up @@ -677,14 +682,14 @@ EXTERNAL SOURCES:

SPEC CHECKSUMS:
boost: 57d2868c099736d80fcd648bf211b4431e51a558
CustomerIO: 4a04f63c9951bced3f2160397e811451cba0de36
customerio-reactnative: 57a15506e537c89802847b819442ab4426de68eb
customerio-reactnative-richpush: 3866204a12a94ce8eaa6630ab39f069dea970b36
CustomerIOCommon: 65752b4280cd24edf8091eba59cae04347999fe1
CustomerIOMessagingInApp: ce4944ec4c9d1dd0d30ea7a0c6aee7137609d7e3
CustomerIOMessagingPush: 6a21e2bd5bb4a6b483671e7703dc011a4deb8178
CustomerIOMessagingPushAPN: 93e371ee9e5208497320bec6325e715db0a8b3ab
CustomerIOTracking: 5eab210defdf8950e0708713f7d95b35b779e056
CustomerIO: 157786b8d83f792f73fea0455389445e80e8f582
customerio-reactnative: 84e011604b93bf59f3d52e70e8444f0d0f8add12
customerio-reactnative-richpush: f875b19d8f750810946e3705ef2a435690ae61ff
CustomerIOCommon: 2f1537b82af71a058b502885ef2604506af15bb4
CustomerIOMessagingInApp: a78f32bc57d6baea2be4c7c7491bf733fb7e0596
CustomerIOMessagingPush: c13903c4256d6d236d3b6bd29b77672b3908e788
CustomerIOMessagingPushAPN: 13b08111e6901630017dc66871ead3d44d1b2f80
CustomerIOTracking: 51dd017df4796203242032b6ffafbc8a9a740fb2
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
FBLazyVector: 5d4a3b7f411219a45a6d952f77d2c0a6c9989da5
FBReactNativeSpec: 3fc2d478e1c4b08276f9dd9128f80ec6d5d85c1f
Expand All @@ -707,6 +712,7 @@ SPEC CHECKSUMS:
React-jsiexecutor: c7f826e40fa9cab5d37cab6130b1af237332b594
React-jsinspector: aaed4cf551c4a1c98092436518c2d267b13a673f
React-logger: da1ebe05ae06eb6db4b162202faeafac4b435e77
react-native-notifications: 4601a5a8db4ced6ae7cfc43b44d35fe437ac50c4
react-native-safe-area-context: 9697629f7b2cda43cf52169bb7e0767d330648c2
React-NativeModulesApple: edb5ace14f73f4969df6e7b1f3e41bef0012740f
React-perflogger: 496a1a3dc6737f964107cb3ddae7f9e265ddda58
Expand Down Expand Up @@ -738,4 +744,4 @@ SPEC CHECKSUMS:

PODFILE CHECKSUM: dd15e298a538ff617275f2a8acfe9f2e3d78fbbf

COCOAPODS: 1.12.1
COCOAPODS: 1.14.3
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