react-native-push-notification / ios

React Native Push Notification API for iOS.
MIT License
743 stars 285 forks source link

Receiving Push Notification's only after close/reopen app. #182

Open game8149 opened 4 years ago

game8149 commented 4 years ago

I'm dealing with this problem since 2 days ago. When I install and open app at first time, allow notification's permission and check that I've received APNS Token and Token Firebase, everything looks fine but, when I send a notification via PostMan FCM API and using my Token FCM, it didn't receive any notification. Surprisedly, when I close and reopen its and resend notification via FCM API, theses notifications arrives quickly... Did somebody deal with this situation?...

Edit (17/09/2020): I tested this app with notifications on iPhone 5s and iPad Air (iOS 12.4.8) and it works fine at first launch, but it doesn't at iPhone 6s (iOS 12.4.8), iPhone 7 Plus , iPhone XR (iOS +13). I don't understand what happens.

Edit2 (18/09/2020): Today I updated my dependencies: "react-native-push-notification" to "^5.1.1", "@react-native-firebase/app" to "^8.4.3" and "@react-native-firebase/messaging" to "^7.8.6", and now iPhone 5s and iPad Air (iOS 12.4.8) don't receive nothing at first launch :(

I'm using (17/09/2020)

"react-native": "0.63.2",
"react-native-push-notification": "^5.1.0",
"@react-native-community/push-notification-ios": "^1.5.0",
"@react-native-firebase/app": "^8.4.1",
"@react-native-firebase/messaging": "^7.8.4",

This is App.js


import React, {
  useEffect,
  useState
} from 'react';
import { Platform, Alert, AppState} from 'react-native'
import { StyleProvider } from 'native-base';
import {
  writeDebug 
} from './src/functions/LoggerService'

import Home from './src/Home';
import getTheme from './src/theme/components';
import variables from './src/theme/variables/commonColor'; 
import NofiticationManagerFCM from './src/functions/NotificationManager';
import NotificationHub from './src/functions/NotificationHub';
import {
  configureDevice,
  requireRPIdentity
} from './src/functions/ConfigDevice';
import LocalNotificationService from './src/functions/NotificationDialog';
import RNBootSplash from "react-native-bootsplash";
import PushNotificationIOS from '@react-native-community/push-notification-ios';
import { write } from 'fs';

let onLoad = false;

const App: React.FC = () => {
  const [onNotificationRecieved, setNofiticationRecieved] = useState(
    false,
  );
  const [notificationBehaviour, setNotificationBehaviour] = useState(
    '',
  );

  const [permissions, setPermissions] = useState({});

  useEffect(() => {
    PushNotificationIOS.addEventListener('notification', onRemoteNotification);
  });

  const onRemoteNotification = (notification) => {
    if(Platform.OS == 'ios' &&(typeof notification.getData) === 'function')
    {
        const isClicked = notification.getData().userInteraction === 1
        Alert.alert('es '+ isClicked,JSON.stringify(notification));
        if (isClicked) {
            // Navigate user to another screen
        } else {
            // Do something else with push notification
        }
    }
    else {
      Alert.alert('es ',JSON.stringify(notification));
    }
  };

  useEffect(() => { 
    onLoad = false;
    async function init (){
      let tokenAccess = await requireRPIdentity();
      if(!tokenAccess)
        Alert.alert("Token de Acceso RP", "No se pudo recuperar el token.");
      await configureDevice(); 
      NofiticationManagerFCM.requestOnlyUserPermission().then(async (auth)=>{ 
        writeDebug("RegistroRemoto con ",auth.toString());
        await NofiticationManagerFCM.registerAppWithFCM(auth);
        await NofiticationManagerFCM.registerFCM(onRegister, onNoti, onOpenNoti);
        LocalNotificationService.configure(onOpenNoti); 
      }); 

      function onRegister(token) {
      }

      function onNoti(remoteMessage) {
        if(AppState.currentState !=='background'){
          LocalNotificationService.showNotification(remoteMessage); 
        }
        NotificationHub.syncNotification(remoteMessage, 2);
      }

      async function onOpenNoti(noti) { 
        await NotificationHub.syncNotification(noti, 3);
      }

      return;
    }

    if(!onLoad){ 
      onLoad=true;
      init().then((x)=>{
      }).catch((err)=>{
        writeDebug('Error en Init',err);
      }).finally(()=>{ 
        RNBootSplash.hide({ duration: 250 });
      }); 
    }

    return () => {
      LocalNotificationService.unregister();
    };
  }, [notificationBehaviour]);

  return (
    <>
      <StyleProvider style={getTheme(variables)}>
        <Home/>
      </StyleProvider>
    </>
  );
};

export default App;

NotificationDialog.js


import PushNotification from 'react-native-push-notification';
import {
  Platform
} from 'react-native';
import
NotificationHub
from './NotificationHub';
import PushNotificationIOS from '@react-native-community/push-notification-ios';
import {
    writeDebug 
} from './LoggerService'

class LocalNotificationService {
  configure = (onOpened) => {
    let parent = this;
    PushNotification.configure({
      onRegister: function (token) { 
        writeDebug('Token Generado',token);
      },
      onNotification: async function (notification) {
        if(Platform.OS === 'ios' && notification ){ 
          try{
            writeDebug('Noti abierta Foreground iOS',notification); 
            await onOpened(notification); 
            notification.finish(PushNotificationIOS.FetchResult.NoData); 
          }
          catch(err){
            writeDebug('Error al abrir Notificación',err);
          }
        }
      },
      // IOS Properties
      permissions: {
        alert: true,
        badge: true,
        sound: true,
      },

      popInitialNotification: true,
      requestPermissions: true,
    });
    this.recoveringNotification();
  };

  recoveringNotification = ()=>{ 
    if (Platform.OS === 'ios'){ 
      PushNotificationIOS.getInitialNotification().then((remoteMessage)=>{ 
        if (remoteMessage) {
          let newNoti = {};
          if(typeof remoteMessage.foreground == 'boolean' && !remoteMessage.foreground){
            newNoti.data = remoteMessage;
            newNoti.notification = remoteMessage;
          }
          else {
            newNoti = remoteMessage;
          }
          NotificationHub.syncNotification(newNoti, 3);
          writeDebug('Noti abierta Background iOS',newNoti);  
        }
      });
    }
    else {
      PushNotification.popInitialNotification((remoteMessage) => {
        if (remoteMessage) { 
          let newNoti = {};
          if(typeof remoteMessage.foreground == 'boolean' && !remoteMessage.foreground){
            newNoti.data = remoteMessage;
            newNoti.notification = remoteMessage;
          }
          else {
            newNoti = remoteMessage;
          }
          NotificationHub.syncNotification(newNoti, 3);
          writeDebug('Noti abierta Background Android',newNoti); 
        } 
      });
    }
  }

  unregister = () => {
    PushNotification.unregister();
  };

  showNotification = (obj) => {
    PushNotification.localNotification({
      ...this.buildAndroidNotification(2),
      ...this.buildIOSNotification(2),
      title: obj.notification.title,
      message: obj.notification.body,
      body: obj.notification.body,
      channelId: 'rn-push-notification-channel-id-4-default-300',
      messageId: obj.messageId,
      vibrate: true,
      vibration: 300,
      priority: 'max',
      importance: 'max',
    });
  };

  buildAndroidNotification = (id) => {
    return {
      id: id,
      largeIcon: 'ic_launcher_round',
      largeIconUrl: 'ic_launcher_round',
      smallIcon: 'ic_stat_onesignal_default', 
      vibrate: true,
      vibration: 300,
    };
  };

  buildIOSNotification = (id) => {
    return {
      alertAction: 'view', 
      userInfo: {
        id: id,
      },
    };
  };

  cancelAllNotifications = () => {
    if (Platform.OS === 'ios') {
      PushNotificationIOS.cancelAllLocalNotifications();
    } else {
      PushNotification.cancelAllLocalNotifications();
    }
  };

  removeDeliveredNotificationById = (notificationId) => {
    PushNotification.cancelLocalNotifications({
      id: `${notificationId}`
    });
  };
}

export default new LocalNotificationService();

NotificationManager.js

import messaging, {firebase} from '@react-native-firebase/messaging'; 
import {
    getData,
    storeData
} from './StorageManager';
import {
    writeDebug,
    writeLog,
    writeSuccess
} from './LoggerService'
import {
    registerNotiHubDevice,
    updateNotiHubDevice
} from './ConfigDevice';
import NotificationHub from './NotificationHub';

class NofiticationManagerFCM {

    getAPNSToken = async () => {
        try{
            if(!messaging().isDeviceRegisteredForRemoteMessages)
                return;
            let tries = 0;
            while (tries < 4) {
            const apnsToken = await messaging().getAPNSToken();
            if (apnsToken !== null) return apnsToken;
            await new Promise((resolve) => setTimeout(resolve, 1000));
            tries++; 
            } 
        }catch(err){
            writeDebug('Error en permisos Noti APNS',err);         
        }
      }

    registerAppWithFCM = async (auth) => { 
        if (Platform.OS === 'ios' ){  
            try{
                let atl = await messaging().registerDeviceForRemoteMessages();
                writeSuccess('APNS Registrered con', auth? auth.toString() :'(Ya solicitado)'); 
                await messaging().setAutoInitEnabled(true);
                let tokenAPNS = await this.getAPNSToken()
                writeDebug('Token APNS', tokenAPNS);   
            }
            catch(err){
                writeDebug('Error APNS', err);
            }
            // } 
        }
    };

    registerFCM = async (
        onRegister,
        onNotification,
        onOpenNotification
    ) => { 
        await this.checkPermission(onRegister); 

        await storeData('sys_notiTokenIdAPNS', null);

        messaging().onTokenRefresh(async (fcmToken) => {
            await storeData('sys_notiTokenId', fcmToken);
            updateNotiHubDevice(fcmToken);
        });

        messaging().onNotificationOpenedApp(async (remoteMessage) => {
            writeDebug('Abierto Noti',remoteMessage);   
            await onOpenNotification(remoteMessage); 
        });

        messaging().setBackgroundMessageHandler(async (remoteMessage) => { 
            writeDebug('Llegada Noti Background',remoteMessage);  
            onNotification(remoteMessage);
        });

        messaging()
            .getInitialNotification()
            .then((remoteMessage) => {
                if (remoteMessage) {
                    NotificationHub.syncNotification(remoteMessage, 2);
                }
            });

        messaging().onMessage((remoteMessage) => {
            writeDebug('Llegada Noti OnMessage',remoteMessage);   
            if (remoteMessage) {
                onNotification(remoteMessage);
            }  
        });
    };

    refreshToken = async () => {
        await messaging().deleteToken();
        await this.requestUserPermission();
    };

    requestUserPermission = async (onRegister) => {
        let userPermission  = await messaging().requestPermission();
        writeDebug('Permiso cedido',userPermission);  
        if(userPermission == messaging.AuthorizationStatus.AUTHORIZED || userPermission == messaging.AuthorizationStatus.PROVISIONAL)
            await this.getFcmToken(onRegister);
        else 
            await storeData('sys_notiTokenId', null);

    };

    requestOnlyUserPermission = async (onRegister) => {
        return messaging().requestPermission();
    };

    getFcmToken = async (onRegister) => {
        let fcmToken = null;
        try{
            fcmToken = await messaging().getToken(); 
        }
        catch(err){ 
            writeDebug('Error al obtener token',err);  
        }
        if (fcmToken) {
            let token = await getData('sys_notiTokenId');
            await storeData('sys_notiTokenId', fcmToken);
            writeDebug('Token en Memoria',token);  
            writeDebug('Token obtenido',fcmToken);  
            if (!token) { 
                await registerNotiHubDevice(fcmToken);
            } else {
                await updateNotiHubDevice(fcmToken);
            } 
        } else {
            writeLog('Token FCM', 'No token received');
        }
    };

    getCurrentToken = async () => {
        let token = await messaging().getAPNSToken();
        return token;
    }

    checkPermission = async (onRegister) => {
        try{
            let enabled =  await messaging().hasPermission(); 
            writeDebug('Tiene Permiso Noti',enabled);   
            if (enabled == messaging.AuthorizationStatus.AUTHORIZED || enabled == messaging.AuthorizationStatus.PROVISIONAL) {
                await this.getFcmToken(onRegister);
            } else {
                await this.requestUserPermission(onRegister);
            }
        }catch(err){
            writeDebug('Error en permisos Noti',err);         
        }
    };
}

export default new NofiticationManagerFCM();
surafelbm commented 3 years ago

@game8149 hey were you able to fix this issue, I am facing the exact same thing.

adbario commented 3 years ago

Looks like the same issue as in https://github.com/invertase/react-native-firebase/issues/4299