Expo: [notifications] selecting notification when app is killed should trigger NotificationResponseReceivedListener

Created on 1 Feb 2020  Β·  53Comments  Β·  Source: expo/expo

πŸ› Bug Report

Environment

Expo CLI 3.11.7 environment info:
System:
OS: macOS 10.15
Shell: 5.7.1 - /bin/zsh
Binaries:
Node: 10.16.3 - /usr/local/bin/node
Yarn: 1.19.1 - /usr/local/bin/yarn
npm: 6.9.0 - /usr/local/bin/npm
IDEs:
Xcode: 11.1/11A1027 - /usr/bin/xcodebuild
npmPackages:
expo: ^35.0.0 => 35.0.0
react: 16.8.3 => 16.8.3
react-native: https://github.com/expo/react-native/archive/sdk-35.0.0.tar.gz => 0.59.8
react-navigation: ^3.0.9 => 3.0.9
npmGlobalPackages:
expo-cli: 3.11.7

Target: iOS

Expected Behavior

When Expo is closed, local notifications still arrive and when pressed open the app to the correct screen.

Actual Behavior

When Expo is closed, local notifications do arrive but when pressed do not open the app to the correct screen.

Notifications bug

Most helpful comment

Experiencing the same on Pixel 4.

      react-native @ sdk-38.0.2.tar.gz => 0.62.2
              expo @ 38.0.8
expo-notifications @ 0.3.3

I have:

  1. added "useNextNotificationsApi": true to the app.json.
  2. confirmed the old Notifications API no longer works with that added.
  3. implemented the listeners as per your example, and tested.
  4. subsequently moved the listeners to the global scope, and tested.
  5. found props.exp (which includes notification) in the Root component – which just seems to be the same as defined in app.json anyway :)

In the global scope, I've defined the listeners as follows:

import * as Notifications from 'expo-notifications';

Notifications.setNotificationHandler({
  handleNotification: async () => ({
    shouldShowAlert: true,
    shouldPlaySound: false,
    shouldSetBadge: false,
  }),
});

Notifications.addNotificationResponseReceivedListener((
  response: Notifications.NotificationResponse
) => {
  console.info('interacted', JSON.stringify(response));
});

Notifications.addNotificationReceivedListener((
  notification: Notifications.Notification
) => {
  console.info('received', JSON.stringify(notification));
});

On device, this turns out to have the following results:

              Foreground    Background   Killed
-------------------------------------------------
   Received    βœ… Yes        ❌ No        ❌ No
 Interacted    βœ… Yes        βœ… Yes       ❌ No ← this is what we're expecting to be "βœ… Yes"

I'm happy to help debug this – if there's anything I can do to help test, please let me know.

All 53 comments

This is in the Expo client app? I've tested it seems to work, so please provide a reproducible demo

It's been a while since we've had any activity on this issue, and seeing as it needs more info before we can properly address it, we will be closing it in one month. If you've found a fix, please share it! Otherwise, please provide the info we asked for, especially a reproducible example. Thanks!

Someone posted this as a Feature Request in January but it seems more like a bug to me.
There was a video posted showing the issue. It occurs when the app is not alive in the background like after it has been force closed or hasn't been used in a while. In the video, in the third example he force closes the app before clicking the notification.

In video I'm showing all 3 scenarios

  1. Foreground (00:00 - 00:22)
  2. Background (minimalised) (00:27 - 00:40)
  3. Closed app (00:50 - 01:10) - not working

https://drive.google.com/open?id=165VuHx3qRQuwZzPS37mDmUJKQjMQ-sxk

Source: https://expo.canny.io/feature-requests/p/background-notification-handling

I got the same problem since I upgraded to expo-notification. I am using sdk38 managed workflow, standalone app (I rebuilt the bundle), and it occurs in both iOS and Android.
Thank you @cruzach for your help!

@cruzach is there any info you need from us? I can provide the code I am using to see if it is possible to reproduce the bug. Thanks!

For me addNotificationResponseReceivedListener doesn't trigger only when app is closed already or user force closes it, it triggers fine when app is foregrounded or backgrounded, even it works in expo-client if its foregrounded or backgrounded, I am testing on Expo SDK 38 and physical iPhone device.

For me addNotificationResponseReceivedListener doesn't trigger only when app is closed already or user force closes it, it triggers fine when app is foreground or background, even it works in expo-client if its foreground or backgrounded, I am testing on Expo SDK 38 and physical iPhone device.

I'm having the same issue. Waiting for the solution or some workaround.

is there any info you need from us?

Nope, I was able to reproduce this with the demo from the docs. We're aware of the issue and will investigate/resolve as soon as we can!

Still investigating, but it seems like the listener may be added too late? When I define

Notifications.addNotificationResponseReceivedListener((response) => {
  console.log("received response!");
});

in the global scope, outside of any component, the listener fires when selecting a notification after the app has been fully killed

@cruzach it is weird because I haven’t changed anything in my code (which worked with sdk37), I simply upgraded to sdk38 and changed the functions according to the new expo-notifications. So, in my case, the listener is added in the same instance as it was before when it worked. If that makes sense! πŸ˜ƒ

Yeah that makes sense, I'm saying in my case moving it outside of the component resolved the issue. Try the code in this gist- https://gist.github.com/cruzach/eadbf47990e57b9ff4c808dd377d44c7

Yeah that makes sense, I'm saying in my case moving it outside of the component resolved the issue. Try the code in this gist- https://gist.github.com/cruzach/eadbf47990e57b9ff4c808dd377d44c7

@cruzach Does this work only in standalone apps? i.e. Using Expo app won't work with this?

Yeah that makes sense, I'm saying in my case moving it outside of the component resolved the issue. Try the code in this gist- https://gist.github.com/cruzach/eadbf47990e57b9ff4c808dd377d44c7

Still not firing up for me even if I move the listener to above component like your gist, only fires when app is foregrounded or backgrounded, If the app is forced closed from the recent apps list, and user taps the notifications app loads showing splash but no alert from the listener's callback. (Testing on iPhone on expo sdk 38)

I am using react-navigation 4, how would I redirect to another screen using this._appNavigator._navigation.push() if listener is outside the component?

Yeah that makes sense, I'm saying in my case moving it outside of the component resolved the issue. Try the code in this gist- https://gist.github.com/cruzach/eadbf47990e57b9ff4c808dd377d44c7

Just tried the code in a standalone App iOS and nothing happens. When the app is running, it does work, but once the App is killed, it doesn't trigger when the push opened the App first time :(

Yeah that makes sense, I'm saying in my case moving it outside of the component resolved the issue. Try the code in this gist- https://gist.github.com/cruzach/eadbf47990e57b9ff4c808dd377d44c7

Still not firing up for me even if I move the listener to above component like your gist, only fires when app is foregrounded or backgrounded, If the app is forced closed from the recent apps list, and user taps the notifications app loads showing splash but no alert from the listener's callback. (Testing on iPhone on expo sdk 38)

I am using react-navigation 4, how would I redirect to another screen using this._appNavigator._navigation.push() if listener is outside the component?

You could use this approach when you can't access the navigation prop.

I'm having the same issue here. Bare workflow with SDK 38.

It works in IOS but not in Android when the app is killed.

I have tested android standalone version on Samsung A31 and listener is working fine on it when app is closed / killed, same thing wasn't working on Samsung Note 8.
Standalone version on iPhone still doesn't hit listener when app is closed / killed.
Edit: Samsung A31 is on Android 10 and Samsung Note 8 was on Android 9. I don't have Note 8 anymore to test it again.

In iOS it works fine.
In android it does not trigger at all.

Scenario on android (real device):

  1. The token itself came up fine.
  2. listeners are registered (I tried inside of useEffect, outside of useEffect and outside of class)
  3. remote push sent to device. - device is ringing and push show up on notification center.
  4. when click on it - it just opens the app. - all logic inside listeners does not execute.

Device:
Nexus 5 - Android Marshmallow (6.0.1)

Expo SDK: 38.0.8
App JSON:

"expo": {
    "android": {
        googleServicesFile: "./google-services.json",
        permissions: []
    },
    "notification": {
      "icon":"./assets/notification.png",
      "color":"#6e2b6b"
    }
}

App.js:

```
import * as Notifications from 'expo-notifications';
...

Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: true,
shouldSetBadge: false,
}),
});

export default function App() {
const [notification, setNotification] = useState(false);
const notificationListener = useRef();
const responseListener = useRef();

useEffect(() => {
registerForPushNotificationsAsync().then(token => setExpoPushToken(token));

notificationListener.current = Notifications.addNotificationReceivedListener(notification => {
  setNotification(notification);
});

responseListener.current = Notifications.addNotificationResponseReceivedListener(response => {
  console.log(response);
});

Notifications.dismissAllNotificationsAsync().then(() => {
  // console.log('dismissAllNotifications');
});
Notifications.setBadgeCountAsync(0).then(res => {
  // console.log('setBadgeCount 0', res);
});

return () => {
  Notifications.removeNotificationSubscription(notificationListener);
  Notifications.removeNotificationSubscription(responseListener);
};

}, []);

return (

);
}

async function registerForPushNotificationsAsync() {
let token;
if (Constants.isDevice) {
const { status: existingStatus } = await Permissions.getAsync(Permissions.NOTIFICATIONS);
let finalStatus = existingStatus;
if (existingStatus !== 'granted') {
const { status } = await Permissions.askAsync(Permissions.NOTIFICATIONS);
finalStatus = status;
}
if (finalStatus !== 'granted') {
return;
}
token = (await Notifications.getExpoPushTokenAsync()).data;
console.log('ExpoPushToken', token);

await fetch('https://www.example.com/setup-push-token?token=' + token, {
  method: 'GET',
  headers: {
    'X-Installation-Id': Constants.installationId
  }
});

} else {
// console.log('Must use physical device for Push Notifications');
}

if (Platform.OS === 'android') {
Notifications.setNotificationChannelAsync('default', {
name: 'default',
importance: Notifications.AndroidImportance.MAX,
vibrationPattern: [0, 250, 250, 250],
lightColor: '#FF231F7C',
});
}

return token;
}

Experiencing same issue on expo 38.0.8

Tried on OnePlus 6T (Android 10) and Samsung galaxy S7 (Android 8), same results.

Yeah that makes sense, I'm saying in my case moving it outside of the component resolved the issue. Try the code in this gist- https://gist.github.com/cruzach/eadbf47990e57b9ff4c808dd377d44c7

Notifications.addNotificationResponseReceivedListener wasn't working at all (at the same spot where listener were working fine before). Moving it outside of the component fixed when app is in background, but nothing happens when app is killed, really annoying _bug_ when you want to redirect your user :/ (but still, expo rocks!)

Any news?

Still investigating, but it seems like the listener may be added too late? When I define

Notifications.addNotificationResponseReceivedListener((response) => {
  console.log("received response!");
});

in the global scope, outside of any component, the listener fires when selecting a notification after the app has been fully killed

Exactly what I'm experiencing: when the app is fully killed, only the listener in the global scope receives a response.

Neither Android nor iOs listener is triggered, though I moved the listener as suggested above.
Is it true that no one is assigned to this yet? I cannot release my product until this works.

Expo CLI 3.22.3 environment info:
System:
OS: macOS 10.15.5
Shell: 5.7.1 - /bin/zsh
Binaries:
Node: 14.5.0 - /usr/local/bin/node
Yarn: 1.22.4 - /usr/local/bin/yarn
npm: 6.14.5 - /usr/local/bin/npm
IDEs:
Android Studio: 4.0 AI-193.6911.18.40.6514223
Xcode: 11.5/11E608c - /usr/bin/xcodebuild
npmPackages:
expo: ^38.0.8 => 38.0.8
react: 16.11.0 => 16.11.0
react-dom: 16.11.0 => 16.11.0
react-native: https://github.com/expo/react-native/archive/sdk-38.0.2.tar.gz => 0.62.2
react-native-web: ~0.11.7 => 0.11.7
react-navigation: ^4.0.10 => 4.4.0
npmGlobalPackages:
undefined: 0.1.0

It shouldn't even be a listener issue. It should be Notifications.getInitialNotification or something along those lines. I've been digging into this for hours, and it looks like there _used_ to be a props.exp.notification that came into the root component. I would love to know the brilliant mind that decided to remove this in favor of requiring everyone to set up a listener with the predictable result of it not even firing for most people.

Experiencing the same on Pixel 4.

      react-native @ sdk-38.0.2.tar.gz => 0.62.2
              expo @ 38.0.8
expo-notifications @ 0.3.3

I have:

  1. added "useNextNotificationsApi": true to the app.json.
  2. confirmed the old Notifications API no longer works with that added.
  3. implemented the listeners as per your example, and tested.
  4. subsequently moved the listeners to the global scope, and tested.
  5. found props.exp (which includes notification) in the Root component – which just seems to be the same as defined in app.json anyway :)

In the global scope, I've defined the listeners as follows:

import * as Notifications from 'expo-notifications';

Notifications.setNotificationHandler({
  handleNotification: async () => ({
    shouldShowAlert: true,
    shouldPlaySound: false,
    shouldSetBadge: false,
  }),
});

Notifications.addNotificationResponseReceivedListener((
  response: Notifications.NotificationResponse
) => {
  console.info('interacted', JSON.stringify(response));
});

Notifications.addNotificationReceivedListener((
  notification: Notifications.Notification
) => {
  console.info('received', JSON.stringify(notification));
});

On device, this turns out to have the following results:

              Foreground    Background   Killed
-------------------------------------------------
   Received    βœ… Yes        ❌ No        ❌ No
 Interacted    βœ… Yes        βœ… Yes       ❌ No ← this is what we're expecting to be "βœ… Yes"

I'm happy to help debug this – if there's anything I can do to help test, please let me know.

Did someone get any clue about this? To me, moving the handler to a global scope solved the issue on Android but not iOS (apparently for others is the opposite).

Still no luck for me... nor in Android, nor in iOS.
Please, help! Can't push the changes until this is fixed :/

I have the same problem (Alcatel 1S running Android Pie). Worth noting that the old version of expo notifications (before SDK 38) behaved as expected here. Please help!
We will have to consider changing libraries if this bug doesn't get fixed.

If this doesn't get fixed soon there should be reliable way to traverse old expo sdk (37) notifications docs so that users can switch back to old API, right now every click on left sidebar navigation in expo docs brings user back to sdk 38 docs, I'll like to know if there is a way to browser old expo docs by sdk version.

Did someone get any clue about this? To me, moving the handler to a global scope solved the issue on Android but not iOS (apparently for others is the opposite).

Yep, it solved for me too on Android. Haven't checked on iOS.

Update : Checked on 4 android devices, Android Versions 6.0.1 (Moto G3), 7.1.1 (Samsung On5 Pro), 9.0 (Mi A1), 9.0 (Redmi Note 7 Pro - MIUI 11.0.10 Stable ).
Working good once the handler was moved out of the component scope (now in global scope).

As we were trying to pinpoint the root cause of this, I wasn't able to reproduce this issue in a local project of mine on SDK 38. I realized that the notification handling component was a class component, rather than functional, and that difference resulted in the proper behavior. Below I'm sharing the diff of taking an absolute bare minimum example (from the docs) of notifications that was a functional component, and after making those changes the notification response listener was then fired correctly in all three scenarios on Android:

  • app foreground βœ…
  • app backgrounded βœ…
  • app killed βœ…

(if you'd rather just see the working code, you can take a look at this snack- https://snack.expo.io/@charliecruzan/exponotificationsresponselistenerclass)

-export default function App() {
-  const [expoPushToken, setExpoPushToken] = useState("");
-  const [notification, setNotification] = useState(false);
-  const notificationListener = useRef();
-  const responseListener = useRef();
-
-  useEffect(() => {
-    registerForPushNotificationsAsync().then((token) =>
-      setExpoPushToken(token)
+export default class App extends React.Component {
+  componentDidMount() {
+    registerForPushNotificationsAsync();
+
+    this.onResponseReceivedListener = Notifications.addNotificationResponseReceivedListener(
+      this.onResponseReceived
     );
+  }

-    responseListener.current = Notifications.addNotificationResponseReceivedListener(
-      (response) => {
-        alert(JSON.stringify(response));
-      }
+  onResponseReceived = async (response) => {
+    alert(JSON.stringify(response));
+  };
+
+  componentWillUnmount() {
+    Notifications.removeNotificationSubscription(
+      this.onResponseReceivedListener
     );
+  }

-    return () => {
-      Notifications.removeNotificationSubscription(responseListener);
-    };
-  }, []);
-
-  return (
-    <View
-      style={{
-        flex: 1,
-        alignItems: "center",
-        justifyContent: "space-around",
-      }}
-    >
-      <Button
-        title="Press to Send Notification"
-        onPress={async () => {
-          await sendPushNotification(expoPushToken);
+  render() {
+    return (
+      <View
+        style={{
+          flex: 1,
+          alignItems: "center",
+          justifyContent: "space-around",
         }}
-      />
-    </View>
-  );
+      >
+        <Button
+          title="Press to Send Notification"
+          onPress={async () => {
+            await sendPushNotification();
+          }}
+        />
+      </View>
+    );
+  }
 }

 // Can use this function below, OR use Expo's Push Notification Tool-> https://expo.io/dashboard/notifications
-async function sendPushNotification(expoPushToken) {
+async function sendPushNotification() {
   await Notifications.scheduleNotificationAsync({
     content: {
       title: "You've got mail! πŸ“¬",

This doesn't mean the issue is solved, because I think there are those who want to use functional components as much as possible, but I thought I would share this as it's a pretty easy workaround to get the behavior you're looking for. I've tested this repeatedly on android and wasn't able to get the listener NOT to fire using a class component, so if you are able to repro that bug using this code please let me know how you did it

Thanks for taking the time to look into this, @cruzach. I tried using the above code and unfortunately, I'm still not seeing any events fire for a killed-state app on iOS/TestFlight, even with a minimal project.

I just created a brand new project, and did only the following steps:

  1. Run expo init and choose a blank template for the managed workflow.
  2. Run expo install expo-notifications.
  3. Replace the content of App.js with the above class-based notifications example.
  4. Build for iOS, upload to App Store Connect, and configure a TestFlight release.

The resulting app successfully handles notifications while the app is open or backgrounded, but the addNotificationResponseReceivedListener callback does not trigger when the app is in a killed state upon receiving the notification.

Let me know if there's any more info that would be helpful, or if I can do anything to help debug.

@rylandbell yeah I mentioned that the above was for Android. Similar to other reports in this thread, I haven't seen this on iOS, but can give that a closer look tomorrow. Is android working for you?

but I thought I would share this as it's a pretty easy workaround to get the behavior you're looking for. I've tested this repeatedly on android and iOS and wasn't able to get the listener NOT to fire using a class component, so if you are able to repro that bug using this code please let me know how you did it

@cruzach I think you said you weren't able to reproduce this on both android and ios using class component, but I have exactly same setup, didn't get the time to move to hooks and functions, I have a few differences in my implementation, I am registering for push notification tokens and listeners in the App's constructor, and using class member functions instead of yours out of class scope async functions, but the result is same, it works only in android, never in ios, Killed app doesn't trigger listener neither from class functions nor from where ever you register the listener (CDM, Constructor, Global Scope) doesn't matter for iOS.

there are those who want to use functional components as much as possible,

Count me as one of these!

sorry @summerkiflain you're right, I edited my comment. In that case- for iOS specifically, is this only happening in the managed workflow for you? I can reproduce it in the managed workflow, but the bare workflow works fine for me

@cruzach yes I am on managed workflow.

I tried adding the listener in the global scope and still isn't working on Android when the app is killed.

This is my App.js

import * as Notifications from "expo-notifications";
Notifications.addNotificationResponseReceivedListener((response) => {
  console.log("received response!");
});

I'm using bare workflow with SDK 38.

Any suggestions?

Same problem here for us. SDK 38. Managed workflow
When app is in background addNotificationResponseReceivedListener is triggered on both iOS and Android when clicking on the notification.
When app is killed, it does not trigger on both platforms as well.

PR is out that should address this issue on iOS, so if you were one of the folks that were seeing this on iOS, thanks for reporting this. It's definitely a frustrating issue, and thanks for taking the time and patience to try out the new notifications module and help us make it better πŸ™‚

The rest of this comment will refer to Android only- to be clear about what I'm able to reproduce:

  • Bare workflow is working across the board (@macuna I believe you're the only one here reporting this in bare, could be mistaken, but you may want to open a separate issue with a reproducible demo included)
  • The Managed workflow:

    • pixel 2, android 10 && Oneplus 6T, android 9

    • listener added in useEffect, notification response is not received when app is killed

    • listener added in componentDidMount, notification response is received when app is killed

    • listener added in global scope, notification response is received when app is killed

This was tested with local notifications fired off after a delay, i.e.:

async function showNotification() {
  await Notifications.scheduleNotificationAsync({
    content: {
      title: "You've got mail! πŸ“¬",
      body: "What would you like to do with it?",
    },
    trigger: { seconds: 3 },
  });
}

Again, sorry this has been nagging so many of you, notifications are never fun to debug

I've spent too many hours looking into this :(
Here's a summary of my testing results, hopefully this can expedite this issue's fix.

Using managed workflow in standalone app.
Fresh start = open app after killing it

Android (Essential phone PH-1):

  • Receives notification on fresh start if responseReceivedListener is in GLOBAL scope or in componentDidMount of class component
  • Does not receive props.exp.notification ever
  • Receives notification while backgrounded regardless of where/when responseReceivedListener is called

iOS:

  • Receives notification on fresh start ONLY through props.exp.notification
  • Does not receive on fresh start even if responseReceivedListener is called in global scope or componentDidMount
  • Receives notification while backgrounded regardless of where/when responseReceivedListener is called

@cruzach Sincerely appreciate all the work you've done here!

listener added in useEffect, notification response is not received when app is killed

this is our intended use case. Still hoping a fix can be found!

PR is out that should address this issue on iOS, so if you were one of the folks that were seeing this on iOS, thanks for reporting this. It's definitely a frustrating issue, and thanks for taking the time and patience to try out the new notifications module and help us make it better πŸ™‚

The rest of this comment will refer to Android only- to be clear about what I'm able to reproduce:

  • Bare workflow is working across the board (@macuna I believe you're the only one here reporting this in bare, could be mistaken, but you may want to open a separate issue with a reproducible demo included)
  • The Managed workflow:

    • pixel 2, android 10 && Oneplus 6T, android 9

    • listener added in useEffect, notification response is not received when app is killed

    • listener added in componentDidMount, notification response is received when app is killed
    • listener added in global scope, notification response is received when app is killed

This was tested with local notifications fired off after a delay, i.e.:

async function showNotification() {
  await Notifications.scheduleNotificationAsync({
    content: {
      title: "You've got mail! πŸ“¬",
      body: "What would you like to do with it?",
    },
    trigger: { seconds: 3 },
  });
}

Again, sorry this has been nagging so many of you, notifications are never fun to debug

Thank you @cruzach.

I'll create a new issue for this, since I've followed the required steps.

In order to add more information to my case, my project is an ejected bare workflow (from SDK 37) and later upgraded to SDK 38.

I don't know if maybe there could be the problem ?

Thanks again.

Sadly, the proposed changes of moving to ComponentDidMount do not work for me
Expo CLI 3.23.2 environment info:
System:
OS: macOS 10.15.6
Shell: 5.7.1 - /bin/zsh
Binaries:
Node: 14.7.0 - /usr/local/bin/node
Yarn: 1.22.4 - /usr/local/bin/yarn
npm: 6.14.7 - /usr/local/bin/npm
IDEs:
Android Studio: 4.0 AI-193.6911.18.40.6514223
Xcode: 11.6/11E708 - /usr/bin/xcodebuild
npmPackages:
expo: ^38.0.8 => 38.0.9
react: 16.11.0 => 16.11.0
react-dom: 16.11.0 => 16.11.0
react-native: https://github.com/expo/react-native/archive/sdk-38.0.2.tar.gz => 0.62.2
react-native-web: ~0.11.7 => 0.11.7
react-navigation: ^4.0.10 => 4.4.0
npmGlobalPackages:
undefined: 0.1.0

iOS - backgrounded, opens app wherever it left off and listener is not invoked
closed - notification opens app at "start", with no recognition of being triggered by a notification response

Android (6) - backgrounded, it works!
closed, it does not.

It may very well work on a more recent Android, but I don't have a device that is any newer, so I cannot test.

Looks like I will have to roll back.
Hopefully this is still being addressed?

I had the same issue and it seems I solved it on some devices by moving the listener as static variable instanced outside the App fn component.

const notificationResponseListener = Notifications.addNotificationResponseReceivedListener(
    (notificationResponse) => {
        console.log('NOTIFICATION TAPPED BY USER', JSON.stringify(notificationResponse))
        if (notificationResponse.actionIdentifier == Notifications.DEFAULT_ACTION_IDENTIFIER) {
            ....
        }
    }
)

export default function App(props) {

    useEffect(() => {
        return () => {
            Notifications.removeNotificationSubscription(notificationResponseListener)
        }
    }, [])
...
}

It doesn't work on some others (like iPhone11) because, I guess, the expo lib initialises too fast and the listener is bound after the initialisation (I suppose)

Any updates on this? We are currently blocked on the same issue

Same on Android, SDK 38, Managed workflow. Works when app is in background, but not when the app is killed.

Same on both iOS and Android, not working when the app is Killed. Managed workflow

@cruzach
For me addNotificationResponseReceivedListener doesn't trigger only when the app is closed already or user force closes it, it triggers fine when the app is foregrounded or backgrounded, even it works in expo-client if its foregrounded or backgrounded, I am testing on Expo SDK 38 and the physical Android device.

Hi guys, i have the same problem...
in standalone app when the app is killed with expo 38 doesn't work.

i try all listener but nothing...

any news about that?

i find this in expo doc -

App was not open, and then opened by tapping the home screen icon | no notification is passed to listener

i need to read the notification property....

many thanks

This is how I handled the problem. Works perfectly but a bit ugly.
There is separate subscription for iOS since the addNotificationResponseReceivedListener still didn't work outside the App component on iOS. LegacyNotifications.addListener posts different object type so I'm just wrapping it to be compatible with expo-notifications Notifications.addNotificationResponseReceivedListener

import { Notifications as LegacyNotifications } from 'expo';
import * as Notifications from 'expo-notifications';
import React, { useEffect } from 'react';
import { Platform } from 'react-native';

let notificationListener;

//Workaround notification not received when app is killed | Android
if (Platform.OS === 'android')
   notificationListener = Notifications.addNotificationResponseReceivedListener(
      ({ notification }) => {
         Defaults.savedNotification = notification;
      }
   );

export default function App() {
   useEffect(() => {
      //Workaround notification not received when app is killed | iOS
      if (Platform.OS === 'ios')
         notificationListener = LegacyNotifications.addListener(({ data }) => {
            Defaults.savedNotification = {
               request: { content: { data: { body: data } } },
            };
         });

      return () => notificationListener?.remove();
   }, []);

I tested send remote notification to killed android standalone app (Expo 38) and event NotificationResponseReceivedListener not fired

I ran into this issue on SDK38 - iOS - Standalone build - Managed workflow.

None of LegacyNotifications.addListener/Notifications.addNotificationResponseReceivedListener trigged when I tap to Notification when app was killed. I decide to use exp.notification from App's props to workaround. :sadly:

If you're seeing this issue on iOS in the managed workflow, as I mentioned above, this was a bug on iOS and has since been solved (see https://github.com/expo/expo/pull/9478). You'll need to wait for SDK 39 for a fix (we plan on releasing at the end of Q3, so not far away). On Android, whether you're in the bare or managed workflow, you can get the correct behavior by calling addNotificationResponseReceivedListener outside of any component, i.e. the same place you're probably calling setNotificationHandler. (I'll update the docs example to include this, but here's an example provided in other bug report concerning the same behavior)

It seems that there is an issue with the EventEmitter on Android, only when the notificationResponseReceiverListener is not added early enough on app launch (i.e. in useEffect). This is the same issue as was reported here, it just seems that the issues are getting confused since it's a different issue on Android vs iOS in both of these cases.

Digging into this more, EventEmitter.emit() _is_ called on Android when the app is opened via a notification, but the listener just hasn't been added in time so the event goes "unheard" (so this seems like it may be more of an issue with EventEmitter than with expo-notifications).

So that people don't continue to be confused and report that they're running into a solved issue, I'm going to close this issue and open a new one that specifies the exact issue (which is android-only) as well as the way to get things working as expected for now

Was this page helpful?
0 / 5 - 0 ratings