React Native SDK Setup

Steps for setting up your Android and iOS React Native app with iZooto to enable app push notifications.

Follow the steps mentioned below.

Step 1: Prerequisites

  • Your iZooto App ID. You can find it under Settings > General in your account.

  • For Android:

  • For iOS:

    • An iOS device (iPhone, iPad, iPod Touch) to test on. The XCode simulator does not support push notifications, so must test on a real device.
    • A Mac with a new version of XCode.
    • An iOS Push Certificate.

Step 2: Add iZooto Dependencies (only for Android)

2.1 Open your app/build.gradle (Module: app) file, add/modify the following lines of code inside the Android > defaultConfig section:

android {
 defaultConfig{
    manifestPlaceholders = [
     	izooto_app_id : 'YOUR_iZOOTO_APP_ID_HERE']
	}
}
835

The iZOOTO_APP_ID will be available on the iZooto panel once you have submitted the FCM details. Refer to our guide on how to do this.

📘

Make sure to change the minSdkVersion to 19.

👍

Sync Gradle

Make sure to press "Sync Now" on the banner that pops up after saving!

Step 3: Add a Notification Extension Service (only for iOS)

The iZootoNotificationExtendsServices allows your iOS application to receive rich notifications with images, buttons, and badges.

3.1 In XCode, select File > New > Target.
3.2 Select Notification Service Extension, then press Next.

3.3 Enter the product name as iZootoNotificationExtendsServices and press Finish.

3.4 In the project navigator, select the top-level project directory and select the iZootoNotificationExtendsServices target in the project and targets list.

Unless you have a specific reason not to, you must set the Deployment Target to be iOS 10.

🚧

Deployment Target

Ensure that the Deployment Target is set to the same iOS version for both the main project and the iZooto Notification Service Extension.

3.5 Open NotificationService.m under iZootoNotificationExtendsServices and replace the entire file's contents with the following code.

#import "NotificationService.h"
 
@interface NotificationService ()
 
@property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver);
@property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;
@property (nonatomic, strong) UNNotificationRequest *receivedRequest;
 
@end
 
@implementation NotificationService

-(void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
  self.contentHandler = contentHandler;
  self.receivedRequest = request;
  self.bestAttemptContent = [request.content mutableCopy];
  
  if (self.bestAttemptContent != nil) {
    [iZooto didReceiveNotificationExtensionRequestWithBundleName:@"<APP_BUNDLE_ID>" soundName:@"<SOUND_NAME_HERE>" isBadge: “<TRUE/FALSE>“ request:self.receivedRequest bestAttemptContent:self.bestAttemptContent contentHandler:self.contentHandler];
  }
  // self.contentHandler(self.bestAttemptContent);
}

-(void)serviceExtensionTimeWillExpire {
  // Called just before the extension will be terminated by the system.
  // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
  self.contentHandler(self.bestAttemptContent);
}
 
@end
#import <UserNotifications/UserNotifications.h>
 
@import iZootoiOSSDK;
 
@interface NotificationService : UNNotificationServiceExtension
 
@end
import UserNotifications
import iZootoiOSSDK

class NotificationService: UNNotificationServiceExtension {
  var contentHandler: ((UNNotificationContent) -> Void)?
  var bestAttemptContent: UNMutableNotificationContent?
  var receivedRequest: UNNotificationRequest!
  
  override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
    
    self.receivedRequest = request;
    self.contentHandler = contentHandler
    bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
    if let bestAttemptContent = bestAttemptContent {
      iZooto.didReceiveNotificationExtensionRequest(bundleName :"<APP_BUNDLE_ID>", soundName: "<SOUND_NAME_HERE>", isBadge: <TRUE/FALSE>, request: receivedRequest, bestAttemptContent: bestAttemptContent,contentHandler: contentHandler)
      }
  }
  
  override func serviceExtensionTimeWillExpire() {
    if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
      contentHandler(bestAttemptContent)
    }
  }
}

Ignore any build errors at this point, step 4 will import iZooto which will resolve any errors.

🚧

Important

  • Ensure to replace the <APP_BUNDLE_ID> with your app's Bundle ID.
  • The <SOUND_NAME> should be left blank if you do want to use any custom sound for notifications.
  • The isBadge parameter should be set to either True or False depending on your use-case.

Step 4. Add App Groups

App Groups allow your app and the iZootoNotificationServiceExtension to communicate when a notification is received, even if your app is not active. This is required for badges and Confirmed Deliveries. Refer to our iOS SDK App Groups Setup guide for the step-by-step instructions for implementing this. This is a mandatory step for push notifications to work efficiently.


Step 5: Changes to the AppDelegate file (only for iOS)

Remove all the contents of the AppDelegate file and add the below code:

#import "AppDelegate.h"

#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import <RNIzooto.h>

#ifdef FB_SONARKIT_ENABLED
#import <FlipperKit/FlipperClient.h>
#import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h>
#import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h>
#import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h>
#import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h>
#import <FlipperKitReactPlugin/FlipperKitReactPlugin.h>

@import iZootoiOSSDK;
@import UserNotifications;

static void InitializeFlipper(UIApplication *application) {
  FlipperClient *client = [FlipperClient sharedClient];
  SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
  [client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]];
  [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
  [client addPlugin:[FlipperKitReactPlugin new]];
  [client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
  [client start];
}
#endif

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
#ifdef FB_SONARKIT_ENABLED
  InitializeFlipper(application);
#endif
  
  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
                                                   moduleName:@"<YOUR APP NAME>"
                                            initialProperties:nil];
  
  rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
  
  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  UIViewController *rootViewController = [UIViewController new];
  rootViewController.view = rootView;
  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];
  UNUserNotificationCenter *center =
  [UNUserNotificationCenter currentNotificationCenter];
  center.delegate = self;
  
  if (launchOptions != nil)
  {
    NSDictionary* userInfo = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
    if (userInfo != nil)
    {
      [self performSelector:@selector(HandleKilledStateNotification:) withObject: userInfo afterDelay:1];
    }
  }
  iZooto.landingURLDelegate = self;
  iZooto.notificationOpenDelegate=self;
  iZooto.notificationReceivedDelegate = self;
  return YES;
}
/* Call the method when notification tap in killed state */
-(void) HandleKilledStateNotification: (NSDictionary*) userInfo {
  [RNIzooto willKillNotificationData:userInfo];
}
/* Received the device token  when app is registered sucessfully  */

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
  [RNIzooto didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
  
}

/* Received the paylaod when app is foreground */
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{
  
  [RNIzooto willPresentNotificaiton:notification.request.content.userInfo];
  [iZooto handleForeGroundNotificationWithNotification:notification displayNotification:@"NONE" completionHandler:completionHandler];
  
}
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:
(void (^)(UIBackgroundFetchResult))completionHandler {
  [RNIzooto didReceiveRemoteNotification:userInfo
                  fetchCompletionHandler:completionHandler];
}
/* Handle the notification tap */
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
         withCompletionHandler:(void (^)(void))completionHandler {
  [RNIzooto didReceiveNotificationResponse:response];
  
  completionHandler();
}


- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
  return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}


- (void)onHandleLandingURLWithUrl:(NSString * _Nonnull)url {
  [RNIzooto onHandleLandingURLWithUrl:url];
}
/* handle the deeplink Data*/
- (void)onNotificationOpenWithAction:(NSDictionary<NSString *,id> * _Nonnull)action {
  [RNIzooto onNotificationOpenWithAction:action];
  
}
- (void)onNotificationReceivedWithPayload:(Payload * _Nonnull)payload {
  NSLog(@"Payload");
}

@end
#import <React/RCTBridgeDelegate.h>
#import <UIKit/UIKit.h>
#import <UserNotifications/UserNotifications.h>
@import iZootoiOSSDK;

@interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate,UNUserNotificationCenterDelegate,iZootoNotificationReceiveDelegate,iZootoLandingURLDelegate,iZootoNotificationOpenDelegate>

@property (nonatomic, strong) UIWindow *window;
@property(nonatomic, weak)id <iZootoLandingURLDelegate> landingURLDelegate;
@property(nonatomic, weak)id <iZootoNotificationOpenDelegate> notificationOpenDelegate;
@property(nonatomic, weak)id <iZootoNotificationReceiveDelegate> notificationReceivedDelegate;

@end

Step 6: Import the iZooto SDK into your XCode Project (only for iOS)

These instructions are for CocoaPods, the most common way to manage dependencies for XCode Projects.

6.1 Make sure your current XCode project is closed and in the project root, open terminal, and run sudo gem install cocoapods.
6.2 Run pod init from the terminal in your project directory.
6.3 Open the newly created Podfile with your favourite code editor or type open Podfile from the terminal in your project directory.
6.4 Add the iZooto dependency under your project name target.

target 'iZootoNotificationExtendsServices' do
    # only copy below line
  pod 'iZootoiOSSDK'

end

6.5 Run the following commands in your terminal in your project directory.

pod repo update
pod install

❗️

Make sure to always open the workspace from now on. You can also do this automatically by running xed . from the root of your project.


Step 7: Add Required Capabilities (only for iOS)

This step will make sure your project is able to receive remote notifications.

❗️

Only do this for the main application target.
Do not do this for the Notification Service Extension.

7.1 Select the root project, your main app target, and "Signing & Capabilities".
7.2 Select "All", then under "Background Modes", check "Remote Notifications". You should see Push Notifications already provided.

7.3 If you do not see Push Notifications enabled, click "+ Capability" and double click "Push Notifications" to add it.


Step 8: Add the iZooto SDK (Android & iOS)

8.1 Navigate to your project directory in a terminal window and run the below command to add the iZooto SDK to your project.

npm install react-native-izooto --save

// OR

npm i react-native-izooto

// OR

yarn add react-native-izooto

👍

Verify

Head over to the package.json file and verify that "react-native-izooto": "^2.5.1" has been added.


👍

Android 13 Supported

Our latest React Native plugin (2.1.4 and above) now supports versions till Android 13 and also includes support for Power Push.


Step 9: Import and Initialize iZooto

9.1 Add the below code to the App.js file to import iZooto SDK to your project.

import iZooto from 'react-native-izooto';

9.2 Add the below snippet of code to your default class in the App.js file to initialize iZooto. The different methods listed can be modified as per requirement.

componentDidMount() {
  if (Platform.OS === 'ios') {
    iZooto.initiOSAppID("YOUR_IZOOTO_APP_ID");
    
    iZooto.addEventListener('onTokenReceived', (token) => {
      console.log("iZooto Device Token", token)
    });
    
    iZooto.addEventListener('onNotificationOpened',(openData) => {
      console.log("Notification Deep Link Data",openData);
    });
    
    iZooto.addEventListener('onWebView',(urlData) => {
      console.log("Notification WebView URL Data",urlData);
    });
    
    iZooto.addEventListener('onNotificationReceived',(data) => {
      console.log("Notification Payload Data ",data);
    });
    
    // const obj = {name: "oadd"};
    // const myJSON = JSON.stringify(obj);
    // iZooto.addUserProperty(myJSON);
    // iZooto.addEvent('AAAAP',myJSON);
    // iZooto.setSubscription(true);
  }
  
  else {
    iZooto.initAndroid(false);
    // false will trigger WebView listener
  	// true will trigger default WebView
    
    iZooto.onNotificationOpenedListener(data => {
      console.log("DeepLink Data Received",data);
    });
    
    iZooto.onNotificationReceivedListener(payload => {
      console.log("Notification Payload",payload);
    });
    
    iZooto.onWebViewListener(landingUrl => {
      console.log("Landing URL",landingUrl);
    });
    
    iZooto.onTokenReceivedListener(token => {
      console.log("Token Received",token);
    });
  }
  
  iZooto.setDefaultTemplate(PushTemplate.TEXT_OVERLAY);
  iZooto.setDefaultNotificationBanner("image_name");
  iZooto.setNotificationSound("sound_name_here");

	/*
  componentWillUnmount() {
  	iZooto.removeEventListener('onNotificationOpened');
    iZooto.removeEventListener('onWebView');
    iZooto.removeEventListener('onNotificationReceived');
    iZooto.removeEventListener('onTokenReceived');
  }
  */

	render() {
  	return (
            <View style={{flex:1,justifyContent: "center",alignItems: "center"}}>
               
                <Text > React Native Library for iZooto  
                   Push Notifications Service </Text>

            </View>
        );
	}
}

The iZooto_app_id will be available on the iZooto panel once you have submitted the APNS details. Refer to our guide on how to do this.

Step 10: Run and Test your app

Build and test your app to make sure your device is successfully subscribed to notifications and that you can receive notifications sent from the iZooto dashboard.

❗️

Make sure that you have configured your FCM Service Account JSON corresponding to your Android Project and APNS Certificate corresponding to our iOS Project on iZooto.

Click here for a guide to configure FCM Details for Android App.
Click here for a guide to configure APNS Certificate for iOS App.


Step 11: Customize what your app does when a notification is clicked or received (Optional)

Notification Handlers

Step 12: Programmatically Triggering the Native Permission Prompt (only for Android 13 and above)

Refer to the iZooto Android 13 Push Notification Developer Update Guide to understand the changes needed to be done in your app to provide support for push notifications if your app has started supporting Android 13 (API level 33) or higher.