# Push Notifications - Mobile App Quick Start This guide helps you integrate push notifications into the ShieldAI React Native mobile app. ## Prerequisites Before starting, ensure: - ✅ Backend push notification infrastructure is deployed - ✅ Firebase project is set up (for Android) - ✅ Apple Developer account is active (for iOS) - ✅ Environment variables are configured on the backend ## Step 1: Install Dependencies ```bash npm install @react-native-firebase/app @react-native-firebase/messaging ``` ## Step 2: Android Setup ### 2.1 Add Firebase to Android Project 1. Go to [Firebase Console](https://console.firebase.google.com) 2. Select your ShieldAI project 3. Add Android app with package name: `com.shieldai.mobile` 4. Download `google-services.json` 5. Place it in `android/app/google-services.json` ### 2.2 Update Build Configuration In `android/build.gradle`: ```gradle buildscript { dependencies { classpath 'com.google.gms:google-services:4.4.0' } } ``` In `android/app/build.gradle`: ```gradle apply plugin: 'com.google.gms.google-services' ``` ### 2.3 Request Permissions In `AndroidManifest.xml`: ```xml ``` ## Step 3: iOS Setup ### 3.1 Enable Push Notifications 1. Open Xcode project 2. Select your app target 3. Go to "Signing & Capabilities" 4. Click "+ Capability" 5. Add "Push Notifications" 6. Add "Background Modes" and check "Remote notifications" ### 3.2 Configure Firebase 1. Download `GoogleService-Info.plist` from Firebase Console 2. Add it to your Xcode project (drag to project folder) 3. Ensure "Copy items if needed" is checked ### 3.3 Add Import in AppDelegate.swift ```swift import FirebaseMessaging import UserNotifications @main class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { FirebaseApp.configure() Messaging.messaging().delegate = self return true } // Request permission func requestAuthorization() { UNUserNotificationCenter.current().delegate = self let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound] UNUserNotificationCenter.current().requestAuthorization( options: authOptions, completionHandler: { granted, error in if granted { DispatchQueue.main.async { UIApplication.shared.registerForRemoteNotifications() } } } ) } // Handle token refresh func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String) { print("FCM token refreshed: \(fcmToken)") // Send new token to backend registerDeviceToken(fcmToken) } // Handle foreground notifications func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { let userInfo = notification.request.content.userInfo print("Foreground notification: \(userInfo)") completionHandler([.banner, .sound, .badge]) } // Handle notification tap func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { let userInfo = response.notification.request.content.userInfo print("Notification tapped: \(userInfo)") completionHandler() } } extension AppDelegate: MessagingDelegate { func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) { print("FCM token received: \(fcmToken ?? "none")") if let token = fcmToken { registerDeviceToken(token) } } } // Helper function to register with backend func registerDeviceToken(_ token: String) { // Call your API to register the device // POST /api/v1/devices/register // Body: { userId, platform: "ios", token, deviceType: "mobile" } } ``` ## Step 4: React Native Integration ### 4.1 Create Notification Service Create `src/services/NotificationService.ts`: ```typescript import messaging from '@react-native-firebase/messaging'; import AsyncStorage from '@react-native-async-storage/async-storage'; import axios from 'axios'; const API_BASE_URL = 'https://api.shieldai.com/api/v1'; export class NotificationService { private static instance: NotificationService; private userId: string | null = null; private constructor() {} static getInstance(): NotificationService { if (!NotificationService.instance) { NotificationService.instance = new NotificationService(); } return NotificationService.instance; } setUserId(userId: string) { this.userId = userId; } async requestPermission(): Promise { try { const authStatus = await messaging().requestPermission(); const enabled = authStatus === messaging.AuthorizationStatus.AUTHORIZED || authStatus === messaging.AuthorizationStatus.PROVISIONAL; if (enabled) { console.log('Push notification permission granted'); await this.registerDevice(); return true; } return false; } catch (error) { console.error('Failed to request permission:', error); return false; } } async registerDevice(): Promise { if (!this.userId) { console.warn('User ID not set, cannot register device'); return; } try { const token = await messaging().getToken(); const platform = Platform.OS === 'ios' ? 'ios' : 'android'; const response = await axios.post(`${API_BASE_URL}/devices/register`, { userId: this.userId, platform, token, deviceType: 'mobile', appName: 'ShieldAI Mobile', appVersion: '1.0.0', }); console.log('Device registered:', response.data); } catch (error) { console.error('Failed to register device:', error); } } setupListeners() { // Foreground messages messaging().onMessage(async (remoteMessage) => { console.log('Foreground message received:', remoteMessage); // Show local notification this.showLocalNotification(remoteMessage); }); // Background messages messaging().setBackgroundMessageHandler(async (remoteMessage) => { console.log('Background message received:', remoteMessage); }); // Notification opened messaging().onNotificationOpenedApp((remoteMessage) => { console.log('Notification opened app:', remoteMessage); // Navigate to relevant screen this.handleNotificationTap(remoteMessage); }); // Check if app was opened from notification messaging() .getInitialNotification() .then((remoteMessage) => { if (remoteMessage) { console.log('App opened from notification:', remoteMessage); this.handleNotificationTap(remoteMessage); } }); } private showLocalNotification(message: any) { // Use react-native-push-notification or similar console.log('Show notification:', message.notification?.title); } private handleNotificationTap(message: any) { // Navigate to relevant screen based on notification data const { alertId, type } = message.data || {}; if (alertId) { // Navigate to alert detail console.log('Navigate to alert:', alertId); } } async deregisterDevice(): Promise { if (!this.userId) return; try { const token = await messaging().getToken(); await axios.post(`${API_BASE_URL}/devices/deregister`, { token, userId: this.userId, }); } catch (error) { console.error('Failed to deregister device:', error); } } } ``` ### 4.2 Initialize in App Component ```typescript // App.tsx import React, { useEffect } from 'react'; import { NotificationService } from './src/services/NotificationService'; const notificationService = NotificationService.getInstance(); function App() { useEffect(() => { // Initialize push notifications notificationService.setupListeners(); }, []); // When user logs in const handleLogin = async (userId: string) => { notificationService.setUserId(userId); await notificationService.requestPermission(); }; // When user logs out const handleLogout = async () => { await notificationService.deregisterDevice(); notificationService.setUserId(''); }; return ( // Your app components ); } ``` ## Step 5: Testing ### Android Emulator 1. Start Android emulator with Google Play Services 2. Install and run app 3. Trigger a test notification from backend 4. Check notification appears ### iOS Device (Required) iOS Simulator does not support push notifications. Use a real device. ### Backend Test ```bash # Test notification API curl -X POST https://api.shieldai.com/api/v1/notifications/send \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "userId": "user-uuid", "channel": "push", "subject": "Test Alert", "body": "This is a test notification from ShieldAI", "priority": "high", "metadata": { "alertId": "alert-uuid", "type": "darkweb_exposure" } }' ``` ## Troubleshooting ### Android Issues **Problem**: Token not received - Check `google-services.json` is in correct location - Verify Firebase project ID matches - Check internet connection on emulator **Problem**: Notifications not showing - Ensure notification permissions granted - Check battery optimization settings - Verify notification channel is created ### iOS Issues **Problem**: Token not received - Verify Push Notifications capability is enabled - Check APNs key configuration in backend - Ensure device is not in development mode if using production certs **Problem**: Notifications not showing - Check notification permissions granted - Verify APNs configuration on backend - Ensure proper certificate/key is used ## Next Steps 1. ✅ Set up Firebase project 2. ✅ Configure APNs on Apple Developer Portal 3. ✅ Implement notification handling in app 4. ✅ Test on Android device/emulator 5. ✅ Test on iOS device 6. ✅ Integrate with DarkWatch and SpamShield alerts 7. ✅ Add notification preferences UI 8. ✅ Implement deep linking from notifications ## Resources - [Firebase Cloud Messaging Docs](https://firebase.google.com/docs/cloud-messaging) - [React Native Firebase Messaging](https://rnfirebase.io/messaging/usage) - [Apple Push Notification Service](https://developer.apple.com/documentation/usernotifications)