Expo: Listener registerd in addlistener is not called when selected in expo 36

Created on 14 Dec 2019  ·  55Comments  ·  Source: expo/expo

🐛 Bug Report

Environment

Expo CLI 3.11.1 environment info:
System:
OS: Linux 4.15 Ubuntu 18.04.3 LTS (Bionic Beaver)
Shell: 5.4.2 - /usr/bin/zsh
Binaries:
Node: 10.16.0 - /usr/local/bin/node
Yarn: 1.12.3 - /usr/bin/yarn
npm: 6.9.0 - /usr/local/bin/npm
npmGlobalPackages:
expo-cli: 3.11.1

Bug On Android

Steps to Reproduce

Follow this git I created. Its basicaly the updated version of the push notification snack.
In the README.md futher information are given.

Expected Behavior

When following the snack and running it via expo start I expected that the notification listener was called like in previous versions, as well as like it was stated in the Expo Documentaion.

Actual Behavior

The notification listener was only called while the app was running but not when the notification was selected while the app was not running.

Reproducible Demo

As stated above here is the Github repo I created regarding the bug.
https://github.com/Renji3/expo-pushnotifications

Android Notifications bug needs repro

Most helpful comment

I sill hope this is reviewed by expo in the near futuer as this makes upgrading to version 36 basicaly impossible

All 55 comments

Hi! I just tested this on an Android pixel, and selected the notification from the notification center triggered the listener. Specifically, using the snack in the docs, the "data" was populated with the new data present in the notification

Can you try this again using the snack example and push notification tool? If it doesn't work, try to provide as much info as possible

Running this snack the same error occures.

If I run the snack while sending push notifications the Data can be received.
If I close Expo including the snack, and then send a push notification. The push notification is received trough expo like it should
clicking on that notification however does only open the App, but does not trigger the listener.
Neither the Origin nor the data variable is set in the App

This occures on an Honor 10

Running this snack the same error occures.

If I run the snack while sending push notifications the Data can be received.
If I close Expo including the snack, and then send a push notification. The push notification is received trough expo like it should
clicking on that notification however does only open the App, but does not trigger the listener.
Neither the Origin nor the data variable is set in the App

This occures on an Honor 10

Hi @Renji3 , did you find any workaround for this issue ? We are having same issue on Android , using expo 36.

@aeshashah sadly not so far. This is the thing stoping us from upgrading to expo36.
The thing is that this bug seems to only come up sometimes. I had cases where it worked on the same App and phone while other moments it did create this given bug.

I'm not sure about the possibility of detaching from expo but at this point this is nothing we want to do yet either.

@aeshashah sadly not so far. This is the thing stoping us from upgrading to expo36.
The thing is that this bug seems to only come up sometimes. I had cases where it worked on the same App and phone while other moments it did create this given bug.

I'm not sure about the possibility of detaching from expo but at this point this is nothing we want to do yet either.

Thanks @Renji3. Is it working on any earlier expo version ? Is there a expo version for which it works on android and iOS both ? For us , with expo 36 it works on iOS. But on Android it doesn’t not when app is closed and launched by tapping notification , it doesn’t trigger handle notification.

@aeshashah it works with expo 35. I had the same issue and downgrading from expo 36 to 35 worked on both iOS and Android.

@aeshashah it works with expo 35. I had the same issue and downgrading from expo 36 to 35 worked on both iOS and Android.

@greedygreen Thanks for suggestion . We will downgrade to expo 35 and try it out.

We redirect to different page , in handle notification function , right now it lands on home screen , and redirect doesnt happen as handle notification doesn't get call , when user taps on notification , and app was launched by it.

So to confirm , with expo 35 , it will add listener for handle notification and also trigger the handle notification function( with the first tap on notification) , when app was launched by tapping on notification , right ?

@aeshashah That's right. We receive the push notification while the app is closed, once we tap on the notification, the app is opened and the function passed to Notifications.addListener() is called and navigates the user to the corresponding screen.

@greedygreen Thank you so much for confirming the steps. We will downgrade to expo 35 , hopefully that will fix the issue for our app.

I can confirm what @greedygreen said as well.
We were on 35 already and everything worked fine. Upgrading to 36 caused the problem.
Downgrading again fixed it again.

Hi @aeshashah downgraded back to 35 and it's fixed. Thank you guys.

@Renji3 @greedygreen thank you so much guys for your help. We also downgraded to expo 35 and it works on both iPhone and android.

Hi @aeshashah downgraded back to 35 and it's fixed. Thank you guys.

Awesome !

I sill hope this is reviewed by expo in the near futuer as this makes upgrading to version 36 basicaly impossible

I sill hope this is reviewed by expo in the near futuer as this makes upgrading to version 36 basicaly impossible

yes , hopefully this open bug will get resolved i future releases.

I've tested this and still can't exhibit the behavior of the listener not firing when opening the app from a notification. Here are the steps:

  • run the code from the snack example I linked earlier locally with expo start, get the push token
  • kill the expo app
  • send push notification using https://expo.io/notifications and the retrieved push token, with {"data":"goes here"} in the JSON data field
  • tap the notification from the device's notification tray
  • app opens and I see Data: {"data":"goes here"}

what phone are you using @cruzach ?

Pixel 2, running Android 9

Same issue with xiaomi mi8 (works fine on iOS)

there is obviously many people having this problem by now
Maybe you could concider using another phone to reproduce it on @cruzach ?

Tested on a OnePlus 6T as well, and can't reproduce the issue 🙁

Hey @Renji3 Did you change anything other than downgrading?
We have the issue with IOS and expo 35. But we are mounting our handler in global, not on componentDidMount but not sure if that is the reason as it works when the app is in foreground or minimised

@cruzach I do confirm the issue, using android 9 and a OnePlus 3T.

When using the snack, with expo and the expo snack closed, when I open a notification,
the data is not displayed in the snack,

edit: also there is something I don't understand with this snack https://snack.expo.io/@charliecruzan/pushnotifications36 When I run the code on android, looks like the code is not the one display in the editor, but a previous version (the snack code display the pushToken)

edit2: So I did some digging, Here what I found.
when I start the app, It looks like it is launched twice. There is indeed 'onCreate' then 'onResume' events. At that point the notification is provided to the activity.
But after that, there is an 'onPause' event, followed by another 'onCreate' and 'onResume' event.
In the second launch, there is no trace of the notification anymore.

@maxired can you share a screen recording of doing these steps:

  • run the code from the snack example I linked earlier locally with expo start, get the push token
  • kill the expo app
  • send push notification using https://expo.io/notifications and the retrieved push token, with {"data":"goes here"} in the JSON data field
  • tap the notification from the device's notification tray
  • app opens and I see Data: {"data":"goes here"}

I've done this on multiple android devices and have not been able to reproduce the behavior

I had the same issue with the addListener callback not being triggered only in Expo SDK v36 (but working in v35).

I was able to fix my issue by changing the syntax to the following:

Notifications.addListener(notification => this.handleNotification(notification));

I'd also make sure you are registering the listener in the root component of your app

I had the same issue on SDK 36. Please fix this serious issue.

Thank you!

I just wanted to add my experience about this issue.
I have the same issue with handling notification clicks from closed app on android.
The thing is that the issue is only about 10% of the time while running the app through expo. But after having installed the app through builded apk it happens consistently.
Phone: Android 9, pocophone f1

@tythiras does it seems to you that the application is launching twice ? For exemple do you see your splashscreen blinking ?

@maxired Actually yes. There is a white screen (splash screen I think) in the start, short blink, a bit more white screen. And then the app is loaded and my activity indicator shown. The blink isn't happening on iPhone, and on iPhone my notifications are working perfectly.

The solution of @chuckwood is not helpfull. In my case thats the syntax I'm using all along.
Putting it at the top level as you mentioned @cruzach is not working either. I'm running:

Notifications.addListener( notification => { console.log("Notification", notification) });

at the beginning of constructor in the root Component.
There is not notification reaching the function. The Console log is never fired.

Could you please open this again and give it more attention? This makes using version 36, as well as the new version 37 (where the problem still exists unusable).
This is becoming a bigger problems as Apple soon will get more strict in regards to UIWebView used in expo 35 and lower.

@Renji3 the issue is already open, but a reliable reproducible example is still needed so if you can provide one please do!

https://github.com/Renji3/expo37notificationBug
Here is again a git with the exact error
The code was directly coppied from your snack: https://snack.expo.io/@charliecruzan/pushnotifications36,
After initializing the folder with expo init beforehand.
The only thing modified is renaming the "AppContainer" to App.js to match the name of the initial App.js

I added a video (errorReproductionVideo.mp4) reproducing the bug and differentiating between the state where the app was not closed beforehand and the state where the app was closed.
It can be seen that if you don't close the app (second time i send notifications) it works, but if it was closed (first and third time) it doesn't work.
I also added step by step instructions again to reproduce.

@cruzach to me the source of the issue is really low level, and maybe, it does not have anything to do with Notification.

As I said before, it seems that the Android activity is restarted.
One of the causes might be a configuration change: https://developer.android.com/reference/android/app/Activity.html#configuration-changes . I don't know anything about how it is managed in React-native and expo, but I would love to have opinions from someone familiar with the subject.

If not a configuration change, then it might be linked to a direct call to startActivity.
There is not much in Expo + React Native, so might be a good place to start the investigation.

WDYT ?
Any suggestion on how to proceed ?

Edit: the further I could trace the relaunch was https://android.googlesource.com/platform/frameworks/base.git/+/master/core/java/android/app/ActivityThread.java#2041 - Now, we need to understand why this happen.

@renji3 does your code in the post work in sdk 35? apparently the listener is still not working when app is closed on my sdk 35..

edited: for sdk 35, the listener is able to work on standalone apk but not the expo app.. is yours like this?

my sdk config is like this after downgrading, but sitll couldnt work, can anyone confirm my config
"expo": "35.0.1",
"react": "16.8.3",
"react-dom": "16.8.3",
"react-native": "https://github.com/expo/react-native/archive/sdk-35.0.0.tar.gz",

@Renji3 can i have ur package.json config file for the sdk 35?

@Renji3 running your repo you shared above locally with expo start and using the android Expo Client version 2.15.1, I am still seeing the correct behavior whether I open a notification with the Expo app running in the background, or completely closed. Tested on both a pixel and a oneplus

SDK 37 - same problem both for apk's and in Android Expo Client 2.15.1. The listener never fires even for an empty project.

It does work most of the time when the Expo Client is in the background and the actual app is closed though.

@adrianloh128 I created the app with expo init in this case so I don't have an expo35 version package.json of this git.

@cruzach I can only talk for my Honor 10 using Android 9 and expo client version 2.15.0 installed on the phone. Obviously other seem to have the issues as well. So if you won't be able to reproduce this maybe you could assign another developer to this issue if one is available.

Xiaomi Mi 9 SE (Android 10) - neither SDK 35, 36 nor 37 have the expected behavior of firing an event on the next tick after a closed app gets opened by tapping on the notification. Both for APK and the Expo Client.

Also, tested with this https://snack.expo.io/@charliecruzan/pushnotifications36 - same problem. There is also noticeable black flicker when I open apk of this app.

@Renji3 i created with expo init too but it has... but there is package.json in your original post's link.
also does the listener work on expo client or only apk?

Ok, so in my case the issue was caused by Android 10's dark\night mode. Likely has to do with #6825. That also explains why only some people encountered it.

The fix is to set userInterfaceStyle to "automatic", it also removes black flashing.

Ok, so in my case the issue was caused by Android 10's dark\night mode. Likely has to do with #6825. That also explains why only some people encountered it.

The fix is to set userInterfaceStyle to "automatic", it also removes black flashing.

I can confirm dark mode was causing this on my mobile. Adding expo.userInterfaceStyle, "automatic". Under app.json fixed it, and removed the double boot of the app on startup.
Well found @danilsk

Is there a way I can get it working for expo:35 ? I am not sure we are ready to update to version 37.

@aonamrata it is working in expo 35

@danilsk , @Tythiras , whoo, that's is great news.
Unfortunately, I don't have dark mode activated, so that is not a direct solution for me ;-)

How did you get to discover dark mode was involved ?

@danilsk @Tythiras good job, will try to upgrade my expo later. but when i try to insert in app.json, it shows me this error
Error: Problem validating fields in app.json. See https://docs.expo.io/versions/v35.0.0/workflow/configuration/
• should NOT have additional property 'userInterfaceStyle'.

@danilsk , @Tythiras , whoo, that's is great news.
Unfortunately, I don't have dark mode activated, so that is not a direct solution for me ;-)

How did you get to discover dark mode was involved ?

Ok my bad. Even If don't use night mode, I set userInterfaceStyle to automatic in app.json, and it seems to do the job.
thanks a lot @danilsk and @Tythiras.

@adrianloh128 from what I understand, in SDK35, userInterfaceStyle is only for iOS, so I guess you would have to upgrade.

@cruzach , now that we have more information about the bug, that is is indeed linked to a restart of the activity and the notification not being kept, I guess you will have enough info to create a new issue ?

i can confirm the solution by @danilsk works in expo 37.. good job on the solution!

thanks @danilsk I can also confirm that this solved the problem and makes this finally usable.
This still should be looked into further by the expo team as the dark mode should not be the reason the notifications do not work.

Big thanks to @all for finding the problem

Yes I was able to repro with Dark mode enabled on an Android 10 device, thanks for the info! Will investigate

Hi all,

Trying to get this to work in Expo 37. It works if I select the notification, but not if I simply receive it. Here's the thing: it DID work at one point, but now it does not. The code is the following (in App.js created by expo init):

const registerForPushNotificationsAsync = async () => {
        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") {
                alert("Failed to get push token for push notification!");
                return;
            }
            await Notifications.setBadgeNumberAsync(0);
        } else {
            alert("Must use physical device for Push Notifications");
        }

        if (Platform.OS === "android") {
            await Notifications.createChannelAndroidAsync("default", {
                name: "default",
                sound: true,
                priority: "max",
                vibrate: [0, 250, 250, 250],
            });
        }
    };

    function _handleNotification(notification) {
        Vibration.vibrate();
        Alert.alert("Notification Received", "Notification");
        console.log(notification);
        // async function updateBadgeNumber() {
        //     console.log("Getting badge number");
        //     const numItems = await Notifications.getBadgeNumberAsync();
        //     console.log("Num notifications: ", numItems);
        //     const breakpoint = "";
        // }
        // updateBadgeNumber();
    }

    // Load any resources or data that we need prior to rendering the app
    React.useEffect(() => {
        async function loadResourcesAndDataAsync() {
            try {
                SplashScreen.preventAutoHide();

                // Load our initial navigation state
                setInitialNavigationState(await getInitialState());

                // Load fonts
                await Font.loadAsync({
                    ...Ionicons.font,
                    "space-mono": require("./assets/fonts/SpaceMono-Regular.ttf"),
                });
                await registerForPushNotificationsAsync();
            } catch (e) {
                // We might want to provide this error information to an error reporting service
                console.warn(e);
            } finally {
                Notifications.addListener((notification) => {
                    console.log("HEY I GOT SOMETHING");
                    _handleNotification(notification);
                });
                setLoadingComplete(true);
                SplashScreen.hide();
            }
        }

        loadResourcesAndDataAsync();
    }, []);

Seeing as this is an iPhone 5 that I'm testing on, Dark Mode isn't an issue. However, I did try setting "userInterfaceStyle" : "automatic", and this did not change anything for me.

@ShaggyKris this issue is unrelated
See https://docs.expo.io/workflow/configuration/ - iosDisplayInForeground

Was this page helpful?
0 / 5 - 0 ratings