react-native-push-notification / ios

React Native Push Notification API for iOS.
MIT License
734 stars 282 forks source link

Category / Notification Action does not trigger onNotification from remote notification when app is quit #329

Open Tristan10 opened 2 years ago

Tristan10 commented 2 years ago

"@react-native-community/push-notification-ios": "^1.8.0" "react-native-push-notification": "^7.3.1" "@react-native-firebase/messaging": "^10.3.1"

I have tried two different solutions to handling notifications on iOS. The first was to send data-only notifications and handle them by using RNFirebase's messaging().setBackgroundMessageHandler and then creating a local notification with PushNotification.localNotification and setting the category. This was working correctly for both iOS and Android for all app states (or so I thought). I began getting reports of iOS users not receiving any notifications. I chalked it up to iOS' restriction on background notifications listed here in their docs: APNS Docs. This is how Android is currently working in my app.

I then tried to send notification + data type payloads for iOS and setting the category. The notifications seem to be received by everyone, but the notification actions are no longer working on iOS. It seems that the callbacks are just not being triggered when the app is in the quit state (swiped away from app tray). They seem to still work correctly when the app is in the background or foreground.

Here is my index.js (modified for brevity)


import { AppRegistry, AppState, Platform } from 'react-native';
import App from './App';
import { name as appName } from './app.json';
import { gestureHandlerRootHOC } from 'react-native-gesture-handler'
import messaging from '@react-native-firebase/messaging';
import { NOTIFICATION_TYPES, REFERENCE_TYPES } from './src/static/models';
import PushNotification from "react-native-push-notification";
import PushNotificationIOS from '@react-native-community/push-notification-ios';

if (Platform.OS === 'android') {
    PushNotification.createChannel({
        channelId: 'pm-default',
        channelName: 'PartyMe Default'
    });
}

messaging().setBackgroundMessageHandler(async remoteMessage => {
    console.log(remoteMessage);
    if (remoteMessage && remoteMessage.data && Platform.OS === 'android') {
        switch (remoteMessage.data.type) {
            case NOTIFICATION_TYPES.FRIEND:
                PushNotification.localNotification({
                    channelId: 'pm-default',
                    group: remoteMessage.data.referenceid,
                    id: remoteMessage.data.devicenotificationid,
                    userInfo: {
                        id: remoteMessage.data.devicenotificationid,
                        ...remoteMessage.data
                    },
                    message: remoteMessage.data.body,
                    title: remoteMessage.data.title,
                    actions: ['Accept', 'Decline'],
                    category: 'invitation',
                    data: remoteMessage.data,
                    invokeApp: false
                });
                break;
            case NOTIFICATION_TYPES.INVITE:
                PushNotification.localNotification({
                    channelId: 'pm-default',
                    group: remoteMessage.data.referenceid,
                    id: remoteMessage.data.devicenotificationid,
                    userInfo: {
                        id: remoteMessage.data.devicenotificationid,
                        ...remoteMessage.data
                    },
                    message: remoteMessage.data.body,
                    title: remoteMessage.data.title,
                    actions: ['Accept', 'Decline'],
                    category: 'invitation',
                    data: remoteMessage.data,
                    invokeApp: false
                });
                break;
            case NOTIFICATION_TYPES.MESSAGE:
                PushNotification.localNotification({
                    channelId: 'pm-default',
                    group: remoteMessage.data.referenceid,
                    id: remoteMessage.data.devicenotificationid,
                    userInfo: {
                        id: remoteMessage.data.devicenotificationid,
                        ...remoteMessage.data
                    },
                    message: remoteMessage.data.body,
                    title: remoteMessage.data.title,
                    actions: ['ReplyInput', 'Mark Read'],
                    reply_placeholder_text: 'Write reply',
                    reply_button_text: 'Reply',
                    category: 'reply',
                    data: remoteMessage.data,
                    invokeApp: false,
                    autoCancel: true,
                    ongoing: false
                });
                break;
        }
    }
    return Promise.resolve();
});

if (Platform.OS === 'ios') {
    PushNotificationIOS.setNotificationCategories([
        {
            id: 'reply',
            actions: [
                { id: 'text', title: 'Text Input', textInput: { buttonTitle: 'Reply' } },
                { id: 'read', title: 'Mark Read' }
            ]
        },
        {
            id: 'invitation',
            actions: [
                { id: 'accept', title: 'Accept' },
                { id: 'decline', title: 'Decline' }
            ]
        }
    ]);
}

PushNotification.configure({
    // This is hit in the following cases:
    // Android - Notification clicked while app is in any state
    // IOS - Any notification action (click, action, etc)
    onNotification: (message) => {
        console.log('Notification Received');
        console.log(message);
        // This basically just makes sure that the app is already loaded
        // (Initial notifications are handled later on)
        //
        message.finish(PushNotificationIOS.FetchResult.NoData);
    },
    onAction: (message) => {
        switch (message.data.type) {
            //
        }
    }
});

AppRegistry.registerComponent(appName, () => gestureHandlerRootHOC(App));

Payload Build

payload = {
                token: oReceiver.devicetoken,
                data: {
                  referencetype: "user",
                  referenceid: senderid,
                  referencename: oSender.displayname,
                  receiverid: receiverid,
                  type: "friend",
                  notificationid: notification.id,
                  title: "Friend Request",
                  body: oSender.displayname + " invited you to be friends."
                },
                notification: {
                  title: "Friend Request",
                  body: oSender.displayname + " invited you to be friends."
                },
                apns: {
                  payload: {
                    aps: {
                      'category': 'invitation'
                    }
                  },
                  headers: {
                    'apns-priority': '5'
                  }
                }
              };
vvdodiya commented 2 years ago

Hello @Tristan10 did you find any solution? I have same issue.

Joshmatjjen commented 2 years ago

Same issue here... I comes after upgrading to the latest version

aajahid commented 2 years ago

Same issue. I can see the app starting up in background in the remote debugger console. But it doesn't fire the onNotification event. But if I send the notification again in this state - it does fire the onNotification event.

cibilabraham commented 1 year ago

Is there a fix for this issue ? Facing the same. When app is closed, the action function is not getting called. Did anyone find a fix for this ?

17Amir17 commented 1 year ago

Damn I'm seeing this too, any fixes?