0.0.13 • Published 5 months ago

react-native-ideo-pns v0.0.13

Weekly downloads
-
License
MIT
Repository
-
Last release
5 months ago

🚀 React Native Push Notifications

This module provides an Apple & Android Push Notification Service integration.
It allows:

  • Requesting notification permissions 📩
  • Retrieving the APNs device token 🔑
  • Listening for APNs token updates 📡
  • Checking the current notification permission status
  • Handling background notification launches 📲

📌 Installation and Setup

npm install react-native-ideo-pns

IOS

1️⃣ Enable Remote Notifications in Xcode

  1. Open Xcode (ios/YourApp.xcworkspace).
  2. Go to Signing & Capabilities > Background Modes.
  3. Enable "Remote notifications".
  4. Add the Push Notifications capability in Signing & Capabilities.

2️⃣ Modify AppDelegate.m to Handle APNs Events

Since APNs registration is handled in AppDelegate.m, we must forward events to the Turbo Module (IdeoPns).

📍 Add the Following Code to ios/AppDelegate.m

#import "AppDelegate.h"
#import <UserNotifications/UserNotifications.h>
#import <React/RCTBridge.h>
#import <React/RCTEventEmitter.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    ...
    UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
    center.delegate = self; // Ensures push notifications can be received

    NSDictionary *remoteNotification = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];

    if (remoteNotification) {
        // Store the notification in NSUserDefaults to be processed when the module is ready
        [[NSUserDefaults standardUserDefaults] setObject:remoteNotification forKey:@"PENDING_NOTIFICATION"];
        [[NSUserDefaults standardUserDefaults] synchronize];
    }
    ...
}

// ✅ Handle Notification Clicks
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
    didReceiveNotificationResponse:(UNNotificationResponse *)response
         withCompletionHandler:(void (^)(void))completionHandler
{
    NSDictionary *userInfo = response.notification.request.content.userInfo;
    [[NSNotificationCenter defaultCenter] postNotificationName:@"NotificationOpened" object:userInfo];
    completionHandler();
}

// ✅ Handle Foreground Notifications
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
       willPresentNotification:(UNNotification *)notification
         withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
    NSDictionary *userInfo = notification.request.content.userInfo;
    [[NSNotificationCenter defaultCenter] postNotificationName:@"NotificationReceived" object:userInfo];
    completionHandler(UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionSound);
}

// ✅ Forward APNs Device Token to `IdeoPns`
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    NSMutableString *tokenString = [NSMutableString string];
    const unsigned char *bytes = (const unsigned char *)[deviceToken bytes];
    for (NSUInteger i = 0; i < [deviceToken length]; i++) {
        [tokenString appendFormat:@"%02x", bytes[i]];
    }

    NSLog(@"🔥 APNs Device Token: %@", tokenString);

    // Store token persistently
    [[NSUserDefaults standardUserDefaults] setObject:tokenString forKey:@"APNsIdeoPns"];
    [[NSUserDefaults standardUserDefaults] synchronize];

    // 🔥 Send token to IdeoPns via NotificationCenter
    [[NSNotificationCenter defaultCenter] postNotificationName:@"APNsIdeoPnsReceived" object:tokenString];
}

// ✅ Forward Failure to `IdeoPns`
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
    NSLog(@"❌ Failed to register for remote notifications: %@", error.localizedDescription);
    [[NSNotificationCenter defaultCenter] postNotificationName:@"APNsRegistrationFailed" object:error.localizedDescription];
}

@end

2️⃣ Modify AppDelegate.h to Handle APNs Events

#import <RCTAppDelegate.h>
#import <UIKit/UIKit.h>
#import <UserNotifications/UserNotifications.h>

@interface AppDelegate : RCTAppDelegate <UNUserNotificationCenterDelegate>

@end

Android

1️⃣ Add to app/build.gradle

dependencies {
  // ... existing dependencies ...
  implementation project(':react-native-ideo-pns')
}

2️⃣ Update MainActivity.java/kt

package com.ideonotifications

import android.content.Intent
import android.os.Bundle
import com.facebook.react.ReactActivity
import com.facebook.react.ReactActivityDelegate
import com.ideopns.NotificationHandler

class MainActivity : ReactActivity() {
    // ... existing code ...
    
    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)        
        NotificationHandler.processIntent(intent)
    }
}

3️⃣ Update MainApplication.java/kt

package com.ideonotifications

import android.app.Application
import com.facebook.react.PackageList
import com.facebook.react.ReactApplication
import com.facebook.soloader.SoLoader
import com.ideopns.IdeoPnsModule

class MainApplication : Application(), ReactApplication {
    // ... existing code ...
    
    override fun onCreate() {
         // ... existing code ...
        // Initialize the IdeoPNS library
        IdeoPnsModule.initialize(this)
    }
}

🧩 Usage

import {
  getDeviceToken,
  requestPermissions,
  onNotificationOpened,
  onNotificationReceived,
  checkNotificationPermission,
  configure
} from 'react-native-ideo-pns';

async function setupNotifications() {
  try {
    console.log('🔄 Starting notification setup...');

    // 1️⃣ Request Notification Permissions
    const granted = await requestPermissions();
    console.log(
      granted ? '✅ Notifications Allowed' : '❌ Notifications Denied'
    );

    // 2️⃣ Check Current Notification Permission Status
    const permissions = await checkNotificationPermission();
    console.log('🔎 Current Notification Permissions:', permissions);

    // 3️⃣ Fetch APNs Device Token
    const token = await getDeviceToken();
    const apiKey = process.env.API_KEY;

    if (token && apiKey) {
      console.log('🔥 Device Token:', token);
      Platform.OS === 'android' && configure(token, apiKey);
      // Send token to your backend server here
    } else {
      console.log('⏳ No Token Available Yet...');
    }
    
    // 4️⃣ Listen for notification events
    const notificationOpenedListener = onNotificationOpened((notification) => {
      console.log('🔔 Notification opened:', notification);
      // Handle notification tap here
    });
    
    const notificationReceivedListener = onNotificationReceived((notification) => {
      console.log('📬 Notification received in foreground:', notification);
      // Handle foreground notification here
    });
    
    // Remember to remove listeners when component unmounts
    return () => {
      notificationOpenedListener.remove();
      notificationReceivedListener.remove();
    };
    
  } catch (error) {
    console.error('❌ Error in setupNotifications:', error);
  }
}

// 🚀 Call the function to initialize notifications
useEffect(() => {
  const cleanup = setupNotifications();
  
  return () => {
    if (cleanup) cleanup();
  };
}, []);

🔍 How it Works

The library handles these key scenarios:

  1. App Cold Launch from Notification: When user taps a notification that launches the app from a closed state
  2. Background/Foreground Notification Tap: When user taps a notification while app is already running
  3. Foreground Notification Reception: When a notification arrives while app is in active use

Implementation Details

  • iOS: Uses NSNotificationCenter and NSUserDefaults to handle notification events and pending notifications
  • Android: Uses NotificationHandler to process intents from notification interactions

📋 Troubleshooting

  • Ensure you've added all required capabilities in Xcode for iOS
  • For Android, verify the correct package names in imports
  • Check that you're properly removing event listeners when components unmount
  • Enable debug logging to trace notification flow

📚 API Reference

requestPermissions()

Request notification permissions from the user.

  • Returns: Promise<boolean> - Whether permissions were granted

getDeviceToken()

Get the current device token for push notifications.

  • Returns: Promise<string|null> - The token string or null if unavailable

checkNotificationPermission()

Check the current notification permission status.

  • Returns: Promise<PermissionStatus> - Current permission status

onNotificationOpened(callback)

Listen for when a notification is opened by user tap.

  • Parameters: callback(notification: object) => void
  • Returns: Subscription - Call .remove() to unsubscribe

onNotificationReceived(callback)

Listen for when a notification is received while app is in foreground.

  • Parameters: callback(notification: object) => void
  • Returns: Subscription - Call .remove() to unsubscribe
0.0.13

5 months ago

0.0.12

5 months ago

0.0.11

5 months ago

0.0.10

5 months ago

0.0.9

5 months ago

0.0.8

5 months ago

0.0.7

5 months ago

0.0.6

5 months ago

0.0.5

5 months ago

0.0.4

5 months ago

0.0.3

5 months ago

0.0.2

5 months ago

0.0.1

5 months ago

0.2.9

5 months ago

0.2.8

5 months ago

0.2.7

5 months ago

0.2.6

5 months ago

0.2.5

5 months ago

0.2.4

5 months ago

0.2.3

5 months ago

0.2.2

5 months ago

0.2.1

5 months ago

0.2.0

5 months ago

0.1.9

5 months ago

0.1.8

5 months ago

0.1.7

5 months ago

0.1.6

5 months ago

0.1.5

5 months ago

0.1.4

5 months ago

0.1.3

5 months ago

0.1.2

5 months ago

0.1.1

5 months ago

0.1.0

5 months ago

1.0.2

5 months ago