If you call Notifications.addResponseReceivedListener in useEffect for example, the listener will not be triggered when opening an app from a completely killed state via a notification. This can also be demonstrated by adding a timeout to componentDidMount as shown here. Without 1 second timeout- events come through; with 1 second timeout- event's do not come through.
I should note that the emit method is getting called in this case.
expo diagnostics & the platform(s) you're targetinghttps://snack.expo.io/@charliecruzan/push-notifications
Need to run the app as a published experience or standalone app (or bare debug build) to see the behavior. Press "show notification" and kill the app, tap the notification, observe that response listener isn't triggered.
The workaround (and possibly long-term solution) is to add the listener outside of any component, then it works as expected (presumably bc of how much sooner it's getting called?). I changed the docs to suggest this so fewer people run into this issue
Hello.
I'm sorry to bug, but your solutions doesn't work for killed app on android. I've tried both solutions:
1) add eventListener in componentDidMount method
```import React, { useEffect, useState } from 'react'
import { AppLoading } from 'expo'
import AppNavigation from './navigation/AppNavigation'
import { cacheFonts, cacheImages } from './helpers/AssetsCaching'
import vectorFonts from './helpers/vector-fonts';
import { Provider, rootStore, useMst } from './models/RootStore'
import { ThemeProvider } from 'react-native-elements'
import NetInfo from '@react-native-community/netinfo';
import Theme from './constants/styles/Theme'
import * as firebase from 'firebase'
import './config/YellowboxConfig'
import './config/moment'
import { FIREBASE_CONFIG } from './config/config'
import { subscribeNotification } from './services/PushNotifiations/PushNotifications'
// import './config/ReactotronConfig'
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {assetsLoaded: false}
}
componentDidMount() {
subscribeNotification()
}
async loadAssetsAsync () {
console.log('here')
const fontAssets = cacheFonts([
...vectorFonts,
{ georgia: require('./assets/fonts/Georgia.ttf') },
{ regular: require('./assets/fonts/Montserrat-Regular.ttf') },
{ light: require('./assets/fonts/Montserrat-Light.ttf') },
{ bold: require('./assets/fonts/Montserrat-Bold.ttf') },
{ UbuntuLight: require('./assets/fonts/Ubuntu-Light.ttf') },
{ UbuntuBold: require('./assets/fonts/Ubuntu-Bold.ttf') },
{ UbuntuLightItalic: require('./assets/fonts/Ubuntu-Light-Italic.ttf') },
]);
await Promise.all([...fontAssets]);
}
render(){
if (!this.state.assetsLoaded) {
return (
onFinish={() => this.setState({assetsLoaded: true })}
/>
);
} else {
return (
)
}
}
}
2) add eventListener in global scope
import React, { useEffect, useState } from 'react'
import { AppLoading } from 'expo'
import AppNavigation from './navigation/AppNavigation'
import { cacheFonts, cacheImages } from './helpers/AssetsCaching'
import vectorFonts from './helpers/vector-fonts';
import { Provider, rootStore, useMst } from './models/RootStore'
import { ThemeProvider } from 'react-native-elements'
import NetInfo from '@react-native-community/netinfo';
import Theme from './constants/styles/Theme'
import * as firebase from 'firebase'
import './config/YellowboxConfig'
import './config/moment'
import { FIREBASE_CONFIG } from './config/config'
import { subscribeNotification } from './services/PushNotifiations/PushNotifications'
// import './config/ReactotronConfig'
subscribeNotification()
export default function App() {
const [assetsLoaded, setAssetsLoaded] = useState(false);
const loadAssetsAsync = async () => {
const fontAssets = cacheFonts([
...vectorFonts,
{ georgia: require('./assets/fonts/Georgia.ttf') },
{ regular: require('./assets/fonts/Montserrat-Regular.ttf') },
{ light: require('./assets/fonts/Montserrat-Light.ttf') },
{ bold: require('./assets/fonts/Montserrat-Bold.ttf') },
{ UbuntuLight: require('./assets/fonts/Ubuntu-Light.ttf') },
{ UbuntuBold: require('./assets/fonts/Ubuntu-Bold.ttf') },
{ UbuntuLightItalic: require('./assets/fonts/Ubuntu-Light-Italic.ttf') },
]);
await Promise.all([...fontAssets]);
};
if (!assetsLoaded) {
return (
onFinish={() => setAssetsLoaded(true) }
/>
);
}
return (
);
}
Where './services/PushNotifiations/PushNotifications' is
import * as Notifications from 'expo-notifications';
export function subscribeNotification() {
console.log('subscribing')
Notifications.addNotificationReceivedListener((response)=>console.log('foreground'))
Notifications.addNotificationResponseReceivedListener((response)=>console.log('background'))
}
Im app logs I see
Finished building JavaScript bundle in 74ms.
subscribing // <------ this is called from subscribeNotification()
Running application on SM-G955F.
package.json
{
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
"eject": "expo eject"
},
"dependencies": {
"@expo/vector-icons": "^10.0.0",
"@react-native-community/masked-view": "0.1.10",
"@react-native-community/netinfo": "5.9.2",
"@react-navigation/drawer": "^5.0.0",
"@react-navigation/native": "^5.0.0",
"@react-navigation/stack": "^5.0.0",
"expo": "^38.0.0",
"expo-blur": "~8.1.2",
"expo-font": "~8.2.1",
"expo-image-picker": "~8.3.0",
"expo-notifications": "^0.5.0",
"firebase": "7.9.0",
"formik": "^2.1.4",
"frisbee": "^3.1.2",
"lodash": "^4.17.15",
"md5": "^2.3.0",
"mobx": "^5.15.4",
"mobx-react-lite": "^1.5.2",
"mobx-state-tree": "^3.15.0",
"moment": "^2.24.0",
"mst-persist": "^0.1.3",
"react": "16.11.0",
"react-dom": "16.11.0",
"react-native": "https://github.com/expo/react-native/archive/sdk-38.0.2.tar.gz",
"react-native-collapsible": "^1.5.1",
"react-native-elements": "^2.2.1",
"react-native-expo-image-cache": "^4.1.0",
"react-native-gesture-handler": "~1.6.0",
"react-native-keyboard-accessory": "^0.1.10",
"react-native-masked-text": "^1.13.0",
"react-native-modal-dropdown": "^0.7.0",
"react-native-reanimated": "~1.9.0",
"react-native-safe-area-context": "~3.0.7",
"react-native-screens": "~2.9.0",
"react-native-snap-carousel": "^3.8.4",
"react-native-timeago": "^0.5.0",
"react-native-tiny-toast": "^1.0.6",
"react-native-web": "~0.11.7",
"reactotron-react-native": "^4.0.3",
"yup": "^0.28.1"
},
"devDependencies": {
"@babel/core": "^7.0.0",
"babel-preset-expo": "^8.2.3"
},
"private": true
}
```
Testing on android device, SDK 38, Managed flow.
Any more suggestions ? :)
If you're testing this while running locally in the Expo client, e.g. with expo start, notification responses don't come through when the app is killed. You should build your app with expo build:android
Hi @cruzach - You wrote on the other thread:
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 #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)
1) You mentioned "the same place you're probably calling setNotificationHandler"...Does setNotificationHandler need to be outside of the component as well? It's currently inside for me and working on android/managed workflow. I'm curious if maybe it breaks in certain cases if I don't put it outside?
2) If you run the addNotificationResponseReceivedListener outside of the component, this implies that the components have not rendered yet which means we may not have access to our navigation library and other things only available until milliseconds later. Is there a recommended way to approach this case? I guess we have to store the responses somewhere and then check when the components load in?
No, there's no problem setting it inside a component so you should be fine
I'm assuming you're using notification responses for deep linking somehow, in which case one way to handle that is by calling Linking.openUrl(<scheme://path/to/screen/with?query=param>) inside the response listener, that way you wonβt need access to the navigation props
Hi @Aryk , I want to share how I workaround this issue on both iOS and Android.
In App.tsx, I receive exp.notification from props and save it into a global variable.
import { _setInitialNotification } from 'src/notificationHandler'
// ....
export default function App({ exp }) {
const didInitialize = React.useRef(false)
if (!didInitialize.current) {
if (exp.notification) {
// NOTE(giautm): Workaround for initial notification issue until SDK39 release.
// https://github.com/expo/expo/issues/6943#issuecomment-677901678
_setInitialNotification(exp.notification)
}
didInitialize.current = true
}
// ....
In notificationHandler.ts
let _initialNotification = null
let _called = false
export function _setInitialNotification(notification: Notification) {
_initialNotification = notification
}
export function _handleInitialOnce(listener: (data: any) => void) {
if (!_called) {
_called = true
if (_initialNotification) {
listener(_initialNotification.data)
}
}
}
In my Navigation (react-navigation@v5), I call _handleInitialOnce with listener to process initial notification.
type ScreenOpener = (screen: string, params: { [key: string]: any }) => void
function useRemoteNotification(opener: ScreenOpener) {
useEffect(() => {
const listener = (data: any) => {
Analytics.track('NOTIFICATION_HANDLE', data)
if (data?.screen) {
const { params = {} } = data
opener(data.screen as string, params)
}
}
_handleInitialOnce(listener)
const subscription = Notifications.addNotificationResponseReceivedListener(
response => listener(response.notification.request.content.data?.body),
)
return () => subscription.remove()
}, [opener])
}
Good stuff, thanks for sharing. I'm going to give it a try but still seems like it won't always work on android. According to this guy, the exp.notification will not come in on android:
https://github.com/expo/expo/issues/6943#issuecomment-666899620
Maybe it does on some phones, but not all of them.
Seems like you have to combine your approach with putting the addNotificationResponseReceivedListener outside as well.
Has the exp.notification consistently come through for you on various android phones?
======
I don't have deep linking working yet, but I should. I will try the Linking.openUrl(<scheme://path/to/screen/with?query=param>) approach.
@cruzach, can you comment on the exp.notification approach for iOS, should I be able to get it working using the approach above and reading the notification through exp.notification?
Hi @Aryk , I want to share how I workaround this issue on both iOS and Android.
In App.tsx, I receive
exp.notificationfrom props and save it into a global variable.import { _setInitialNotification } from 'src/notificationHandler' // .... export default function App({ exp }) { const didInitialize = React.useRef(false) if (!didInitialize.current) { if (exp.notification) { // NOTE(giautm): Workaround for initial notification issue until SDK39 release. // https://github.com/expo/expo/issues/6943#issuecomment-677901678 _setInitialNotification(exp.notification) } didInitialize.current = true } // ....In
notificationHandler.tslet _initialNotification = null let _called = false export function _setInitialNotification(notification: Notification) { _initialNotification = notification } export function _handleInitialOnce(listener: (data: any) => void) { if (!_called) { _called = true if (_initialNotification) { listener(_initialNotification.data) } } }In my Navigation (react-navigation@v5), I call
_handleInitialOncewith listener to process initial notification.type ScreenOpener = (screen: string, params: { [key: string]: any }) => void function useRemoteNotification(opener: ScreenOpener) { useEffect(() => { const listener = (data: any) => { Analytics.track('NOTIFICATION_HANDLE', data) if (data?.screen) { const { params = {} } = data opener(data.screen as string, params) } } _handleInitialOnce(listener) const subscription = Notifications.addNotificationResponseReceivedListener( response => listener(response.notification.request.content.data?.body), ) return () => subscription.remove() }, [opener]) }
exp.notification is not documented and not explicitly supported, so relying on that feature isn't recommended
exp.notificationis not documented and not explicitly supported, so relying on that feature isn't recommended
Got it, so for ios is there any work around at the moment (besides ejecting)? I suppose checking for exp.notification and using that is better than nothing.
Using the legacy notifications API listener works, as well. Other than that there's no workaround besides waiting for SDK 39 π sorry that you pretty much just have to wait
If you're testing this while running locally in the Expo client, e.g. with
expo start, notification responses don't come through when the app is killed. You should build your app withexpo build:android
Thank you for reply, yes this works. Just to clarify - to test any changes related to handling notifications when app is killed I have 2 options 1) eject from expo and test locally 2) create expo build. No other options, correct?
Thanks again for your help
You can also run expo publish and test in the Expo client app through the published project
@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.
Here is the code:
`import React from 'react'
import { StyleSheet, Dimensions, ScrollView, ActivityIndicator } from 'react-native'
import { Block, theme } from 'galio-framework'
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import * as Notifications from 'expo-notifications';
import * as Permissions from 'expo-permissions'
import Constants from 'expo-constants';
const { width } = Dimensions.get('screen')
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: false,
shouldSetBadge: false,
}),
});
class Dashboard extends React.Component {
constructor (props, context) {
super(props, context)
state = {
expoPushToken: '',
notification: {},
}
}
componentDidMount () {
this.props.getAutomatedOptions()
this.registerForPushNotificationsAsync()
this._notificationSubscription = Notifications.addNotificationResponseReceivedListener(this._handleNotification)
this._notificationListener = Notifications.addNotificationReceivedListener(notification => {
// console.log('received_notification', notification)
});
}
_handleNotification = notification => {
this.setState({ notification: notification.notification })
console.log('notification.origin', notification.notification.request.content.data)
};`
- I'm assuming you're using notification responses for deep linking somehow, in which case one way to handle that is by calling
Linking.openUrl(<scheme://path/to/screen/with?query=param>)inside the response listener, that way you wonβt need access to the navigation props
@cruzach is there anything about linking not working when it's running via addResponseReceivedListener? As linking (opening a particular page via Linking.openURL) seems to work when the app is not killed (routes to the correct page) but only opens the app when the app is killed.
I opened this new issue to try and keep the conversation focused around the root issue, and this thread is turning into troubleshooting one of the resulting problems, which I've already shared the answer for in the original issue- https://github.com/expo/expo/issues/6943. Any comments posted here that are answered in the other issue will be marked as off-topic (sorry to do this, but too many off-topic comments makes discussing the original issue I posted much more difficult)
@arveenkumar55 please refer to this comment
@xLesterGG as far as I know there's no problem running Linking.openUrl from addResponseReceivedListener. However, maybe it's easier for you to follow this react navigation guide on navigating outside of your component, rather than using Linking.openUrl
Hi @cruzach,
Works when app is in background, but not when the app is killed.
The issue still persist on Android with both SDK 38 and SDK 39 in a managed workflow.
I try to move out addNotificationResponseReceivedListener outside of my component as suggested, but it doesn't work.
Thanks
It is noted in the React documentation that useEffect is called after paint and useLayoutEffect is called 'synchronously after all DOM mutations' hence 'useLayoutEffect fires in the same phase as componentDidMount and componentDidUpdate'.
https://reactjs.org/docs/hooks-reference.html#timing-of-effects
https://reactjs.org/docs/hooks-reference.html#uselayouteffect
As such I have tested useLayoutEffect and still had no success.
Further to that, my specific implementation to navigate on notification was rather inconvenient when being placed outside the navigation container. For any others who have this issue and use ReactNavigation, my specific workaround here was to make a navigation container ref with a promise version, allowing await for the navigation to be mounted before completing the notification handling.
Setup the ref for the navigation container (ignore the typescript typings if relevant), the navigation ref promise only resolves after items have been mounted inside the navigation container (this is reason for checking "getRootState())".
import { createRef } from "react"
import { NavigationContainerRef } from "@react-navigation/core"
const navigationRef = createRef<NavigationContainerRef>()
export const navigationRefPromise: Promise<typeof navigationRef> = new Promise((resolve) => {
const checkValue = () => {
if (navigationRef.current && navigationRef.current.getRootState()) {
return resolve(navigationRef)
}
setTimeout(checkValue, 50)
}
checkValue()
})
export default navigationRef
When processing the notification, if navigation data is present and results in a valid navigation action (based on navigation linking config), complete the navigation dispatch after the navigation ref promise has resolved.
addNotificationResponseReceivedListener((notificationResponse) => {
const notificationData = notificationResponse.notification.request.content.data
if (hasKeyGuard(notificationData, "navigationLink") && typeof notificationData.navigationLink === "string") {
try {
const state = getStateFromPath(notificationData.navigationLink, linking.config)
if (state) {
const action = getActionFromState(state)
navigationRefPromise.then((navRef) => {
if (action && navRef.current) {
navRef.current.dispatch(action)
}
})
}
} catch (error) {
alert(error)
}
}
})
Hi @cruzach,
Works when app is in background, but not when the app is killed.
The issue still persist on Android with both SDK 38 and SDK 39 in a managed workflow.
I try to move outaddNotificationResponseReceivedListeneroutside of my component as suggested, but it doesn't work.Thanks
Same problem here. Have also tried moving addNotificationResponseReceivedListener outside of App.js with no luck. Background and foreground works fine. Edit: Running SDK 39 in managed workflow.
Hi @cruzach,
Works when app is in background, but not when the app is killed.
The issue still persist on Android with both SDK 38 and SDK 39 in a managed workflow.
I try to move outaddNotificationResponseReceivedListeneroutside of my component as suggested, but it doesn't work.
ThanksSame problem here. Have also tried moving
addNotificationResponseReceivedListeneroutside of App.js with no luck. Background and foreground works fine. Edit: Running SDK 39 in managed workflow.
Hi, I too have the exact same issue. SDK 39 managed workflow. Tried it on standalone Android and iOS, inside useEffect or in the same place as Notifications.setNotificationHandler with no luck. If I can provide any other information to help find this issue please let me know.
Confirming same problem as @KlasRobin, @antwaven, and @ozerty. Background/foreground work fine, just not when app is killed/not running. Also managed workflow, SDK 39.
Yes. Same thing. Doesn`t trigger when app is fully closed. Expo 39, android. iOs works perfect.
I can also confirm the same issue. Also moving addNotificationResponseReceivedListener to App.js doesn't worked.
same issue here as @coopbri, @KlasRobin, @antwaven, and @ozerty. Background/foreground work fine, just not when app is killed/not running.
Tested in Android managed workflow, also in standalone apps, SDK 38.
Same issue here. Tried all the suggested workarounds, nothing works. Also moving addNotificationResponseReceivedListener to App.js doesn't work. Updated to SDK 39 but the same issue.
There is no problem on iOS
when using the old notifications-api, there is also the same issue on android. Have you got any suggestions?
Same issue, I follow documentation https://docs.expo.io/versions/latest/sdk/notifications/ but it doesn't work, addNotificationResponseReceivedListener but also doesn't work:
notificationListener.current = Notifications.addNotificationReceivedListener(notification => {
setNotification(notification);
});
the listener doesn`t trigger on Android using Expo SDK 39.
@franamu Are you saying addNotificationReceivedListener doesn't work for you? That method is only supposed to work when the app is foregrounded or backgrounded. addNotificationResponseReceivedListener is the only method between the two that is supposed to work even when the app is closed.
@coopbri yep the two listeners do not work at all on Android.
I can receive the push notification but I canΒ΄t read the data or execute a function.. I just only see the notification.
That is strange. addNotificationReceivedListener works for me inside of a useEffect in the App component:
const App = () => {
useEffect(() => {
const sub = Notifications.addNotificationReceivedListener((res) => { ... });
return () => {
sub.remove();
};
}, []);
return (...);
};
EDIT: Android, SDK 39
@coopbri yes my bad, addNotificationReceivedListener it is working as expected i forgot to specify the channelId for Android Device.
The request should be:
With Axios:
var axios = require('axios');
var data = JSON.stringify({"to":"ExponentPushToken[...]","channelId":"1","sound":"default","title":"Title Example","body":"And here is the body!","data":{"data":"goes here"}});
var config = {
method: 'post',
url: 'https://exp.host/--/api/v2/push/send',
headers: {
'Content-Type': 'application/json'
},
data : data
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
@franamu does that work with a cold-start on android as well? Does the channelId do something on ios? did you create the channeld 1 on the device or is it default?
@franamu Awesome! Glad that works at least.
@andreas-arkulpa nop if I close the app doesn't work but we can try generating the apk and test it. channelId is only for Android. The 1 it just an example but works fine to test it (is not the default). I will create the apk and see if it works.
@franamu thx for the information! Would be nice if you can let me know it it works at startup with the generated apk. :)
Hey all, I have been trying to reproduce this issue and the best I have come up with was failing to get the notification response when the listener is being registered in useEffect. I was not able to not get the response when registering the listener in global scope or useLayoutEffect.
When it comes to timing, I have been consistently getting similar outputs:
14:00:26.571: Listener registered in global scope
14:00:26.783: Listener registered in useLayoutEffect
14:00:26.798: Global scope listener triggered
14:00:26.808: useLayoutEffect listener triggered
14:00:26.822: Listener registered in useEffect
There is a possibility there's a bug in expo-notifications that will be solved by #10773 soon (pending response being consumed by non-emitter, thus never being emitted to JS), but from my testing usually listeners registered in global scope or useLayoutEffect should work.
My suggestion is to always register notification response listener in the global scope (useLayoutEffect probably works here because I'm not doing any fancy stuff like preloading assets, loading state from AsyncStorage etc. before rendering the application).
import * as Notifications from "expo-notifications";
import React, { useState, useEffect, useRef, useLayoutEffect } from "react";
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: false,
shouldSetBadge: false,
}),
});
Notifications.addNotificationResponseReceivedListener(
() => console.log("Global scope listener triggered")
);
console.log("Listener registered in global scope");
export default function App() {
useEffect(() => {
const subscription = Notifications.addNotificationResponseReceivedListener(
() => console.log("useEffect listener triggered")
);
console.log("Listener registered in useEffect");
return () => {
subscription.remove();
};
}, []);
useLayoutEffect(() => {
const subscription = Notifications.addNotificationResponseReceivedListener(
() => console.log("useLayoutEffect listener triggered")
);
console.log("Listener registered in useLayoutEffect");
return () => {
subscription.remove();
};
}, []);
return (/* ...doesn't matter... */);
}
expo-notifications if it works for all of youI would like to provide some sensible solution for all problems you may face⦠I've come up with something along the lines of:
import { Subscription } from "@unimodules/core";
import * as Notifications from "expo-notifications";
import { NotificationResponse } from "expo-notifications";
import { useEffect, useLayoutEffect, useState } from "react";
import { NativeEventEmitter } from "react-native";
// Event emitter used solely for the purpose
// of distributing initial notification response
// to useInitialNotificationResponse hook
const eventEmitter = new NativeEventEmitter();
// Initial notification response caught by
// global subscription
let globalInitialNotificationResponse:
| NotificationResponse
| undefined = undefined;
// A subscription for initial notification response,
// cleared immediately once we believe we have caught
// the initial notification response or there will be none
// (by useInitialNotificationResponse hook).
let globalSubscription: Subscription | null = Notifications.addNotificationResponseReceivedListener(
(response) => {
// If useInitialNotificationResponse is already registered we want to
// notify it
eventEmitter.emit("response", response);
// If useInitialNotificationResponse isn't registered yet, we'll provide it
// with good initial value.
globalInitialNotificationResponse = response;
console.log("Global scope listener triggered");
ensureGlobalSubscriptionIsCleared();
}
);
console.log("Listener registered in global scope");
function ensureGlobalSubscriptionIsCleared() {
if (globalSubscription) {
globalSubscription.remove();
globalSubscription = null;
console.log("Global scope listener removed");
}
}
/**
* Returns an initial notification response if the app
* was opened as a result of tapping on a notification,
* null if the app doesn't seem to be opened as a result
* of tapping on a notification, undefined until we are sure
* of which to return.
*/
export function useInitialNotificationResponse() {
const [
initialNotificationResponse,
setInitialNotificationResponse,
] = useState<NotificationResponse | null | undefined>(
globalInitialNotificationResponse
);
useLayoutEffect(() => {
// Register for internal initial notification response events
const subscription = eventEmitter.addListener("response", (response) => {
console.log("Inner listener triggered");
setInitialNotificationResponse(response);
});
console.log("Inner listener registered");
// In case global subscription has already triggered
// and we missed the eventEmitter notification reset the value
setInitialNotificationResponse(
(currentResponse) => currentResponse ?? globalInitialNotificationResponse
);
// Clear the subscription as hook cleanup
return () => subscription.remove();
}, []);
useEffect(() => {
// If there was an "initial notification response"
// it has already been delivered.
ensureGlobalSubscriptionIsCleared();
// Ensure the value is not undefined (if by this time
// it's still undefined there was no "initial notification response").
setInitialNotificationResponse((currentResponse) => currentResponse ?? null);
}, []);
return initialNotificationResponse;
}
could you please try and use it in your project and see if it allows you to get the initial notification response if there should be one? The useInitialNotificationResponse hook should be able to replace any global scope listeners you may have registered for this purpose.
Note I have only tested it on Android.
If it doesn't work for you, could you please let me know and attach logs from the device? An example would be:
2020-10-23 19:45:25.053 15941-15970/? I/ReactNativeJS: Listener registered in global scope
2020-10-23 19:45:25.057 15941-15970/? I/ReactNativeJS: Running "main" with {"rootTag":1}
2020-10-23 19:45:25.093 15941-15970/? I/ReactNativeJS: { initialNotificationResponse: undefined } (from console.log inside the app)
2020-10-23 19:45:25.239 15941-15970/? I/ReactNativeJS: Inner listener registered
2020-10-23 19:45:25.245 15941-15970/? I/ReactNativeJS: Inner listener triggered
2020-10-23 19:45:25.247 15941-15970/? I/ReactNativeJS: Global scope listener removed
2020-10-23 19:45:25.262 15941-15970/? I/ReactNativeJS: { initialNotificationResponse: β¦ } (from console.log inside the app)
Thanks @sjchmiela
I will give a try !
I just fixed the problem by adding "useNextNotificationsApi": true in the config file.
Looks like I totally missed this part when reading the docs.
It solved all of my problems. Now, addNotificationResponseReceivedListener works fine everywhere.
@ozerty β thanks! π
@uchamb β oh shoot, sorry! Should have thought of this when reading _works on iOS, doesn't work on Android_ instead of blaming the Platform immediately. π Happy to hear everything works ok now!
Awesome @sjchmiela! I can tell you spent a lot of time on that. Unfortunately I already have useNextNotificationsApi: true set in my config unlike @uchamb without luck, but I will give your solution a try and report back. Thanks for all of your hard work.
Any news on this issue? I have also used useNextNotificationsApi: true but still no notification response when the listener is being registered in useEffect of the component. I was not able to get the response when registering the listener in global scope or useLayoutEffect. For us it is important to use navigation when notification is taped so to avoid complications we need it in components, not App.tsx.
Thanks
Sorry it took me so long! Trying your solution, @sjchmiela:
addNotificationResponseReceivedListener in global scope did not trigger,addNotificationResponseReceivedListeners inside of App component (useEffect, useLayoutEffect) did not trigger, however the console.logs outside of the listener code were executed (console.log("Listener registered in useEffect"); and console.log("Listener registered in useLayoutEffect");).Both of the above are while the app was not running, and I tested multiple times with consistency.
Like @milennaj, my use case involves navigation (with React Navigation) and I am trying to trigger the listener inside of a deeper component as well (specifically, the first screen in the navigator).
EDIT: I noticed also that the same applies to the first screen (component) in my navigator, the useEffect/useLayoutEffect consistently trigger after a notification is pressed, however the addNotificationResponseReceivedListener code does not.
any news regarding this bug?
i tried everything and as @coopbri already said nothing is work for the case when app was killed (Android) π,
addNotificationResponseReceivedListener is not fired when pressing on he push notification.
@Maoravitan have you tried using addNotificationResponseReceivedListener inside a class component as opposed to a functional component? This was the approach that worked for me.
@sealedHuman - Could you show us a quick example? Do you put the Notifications.addNotificationResponseReceivedListener call in the componentDidMount or componentWillMount?
I tried:
class Test extends React.Component {
componentDidMount() {
Notifications.addNotificationResponseReceivedListener(
response => Alert.alert(undefined, "first")
)
}
render () {
return null;
}
}
And put that as the first element that rendered in my app and it also didn't work.
I also tried putting this at the very top of my app.tsx as the basically the first thing that gets called.
Notifications.addNotificationResponseReceivedListener(
response => Alert.alert(undefined, "first")
)
I could not get it to work consistently. Sometimes it would work from a dead start, then I rebuild the app, try again, and it doesn't work.
Running Galaxy S8 on Managed 39 SDK.
I have a large app and Galaxy S8 is a slow phone, could that have something to do with it? It's strange because I install the listener as literally the first thing in the app and it still doesn't work.
I've tried also putting it in useLayoutEffect on the top level component and that also didn't work.
I'm completely out of ideas.
@sjchmiela, how exactly does your solution work in the case where the addNotificationResponseReceivedListener is not getting fired at all?
@Aryk - I am basically doing what you are doing in that code snippet you posted. I did have an issue where I had to move some asynchronous font loading I was doing in order to ensure that the app was rendering my notification handler component straight away and not being delayed in any way.
In your example code, where is Test component being rendered?
Also, you probably have this set, but just checking. Do you have have "useNextNotificationsApi": true, set in app.json?
@sealedHuman, yes I have useNextNotificationsApi: true in my app.json. Thx for checking.
I literally put the
I mean, if I'm literally calling this:
Notifications.addNotificationResponseReceivedListener(
response => Alert.alert(undefined, "first")
)
at the very top of my app, what else can I possible do better than that? Is it "too early" in the execution maybe?
The workaround (and possibly long-term solution) is to add the listener outside of any component, then it works as expected (presumably bc of how much sooner it's getting called?). I changed the docs to suggest this so fewer people run into this issue
@cruzach - I'm not sure it has to do with how soon it's getting called because I put the addNotificationResponseReceivedListener call at the very beginning of my app just to see if I can get the listener to trigger and I cannot get it to trigger from a dead-start on Android more than 5% of the time.
Could it be that the event that is triggering the listener could potentially not be getting the notification on a dead start? So therefore, despite where I'm installing the listener, it will never get called?
@Aryk - That is a head-scratcher, for sure. Do you happen to have a full snack I could look at?
That's the problem, I can't reproduce it, but I will try today.
@coopbri @Maoravitan @ozerty @milennaj @beDenz @andreas-arkulpa @abdymm @uchamb
Are you guys still experiencing this issue? Anyone of you have been able to get it working by putting this call first in your app:
Notifications.addNotificationResponseReceivedListener(
response => Alert.alert(undefined, "first")
)
Yes, no matter if it is in the component or outside of component at the beginning of App.tsx this event never fires when app is closed. Tested on Motorola - moto g pro device.
I'm having the same problem. Works on iOS in all cases and on Android if app is started but not if app is killed. SDK39, testing on Samsung Galaxy S20, Android 10.
I tried running the "should-work solution" from @sjchmiela an my device (running it through Expo) but I seem to get the same problem.
If app is open in background:
=> App started
Listener registered in global scope
=> Push received by phone and clicked on
Global scope listener triggered
Global scope listener removed
If app + Expo are killed
=> Push received by phone and clicked on (This starts the app)
Listener registered in global scope
=> The listner is never triggered
app + Expo
Do you mean you're testing the behavior in Expo client? Frankly speaking I haven't been testing this in Expo client, only in bare workflow. Maybe the problem lies here? π Expo client has some middleware code that in theory could consume the notification before the app would be able to receive itβ¦
Is there anyone here that wasn't able to receive the notification response in bare workflow?
Is there anyone here that that is able to reproduce this issue in a standalone app with either
Another thing is that I think in upcoming SDK40 it may actually start to work as we've introduced some behind-the-scene changes that could fix it, but we won't know for sure until we release it! π (It does work when I test it in bare workflow.)
how exactly does your solution work in the case where the addNotificationResponseReceivedListener is not getting fired at all?
Well, my solution only works if it is getting fired. π
Tested on Motorola - moto g pro device.
I actually have that one as my test device! In bare workflow I wasn't able to make it not work.
I have the same problem with the addNotificationResponseReceivedListener not getting triggered if I run it in the Expo client as if I'm running the stand alone app.
When I tried your solution I ran it in the expo client. I will have a go and try it in a stand alone app too. It just takes a little longer as I will upload it to Google play for testing since I don't have any development platform for Android.
I am testing with Expo client, but also this bug is present on a released app in production, available on Google Play store. As I said it is important for us that we could use navigation (react navigation) because tapping on notification we want to open a certain modal. Even if we use a workaround which is available with react-navigation 5 where you can access navigation in App file it will not fix this issue since the code in the response of addNotificationResponseReceivedListener will never execute. In any case since iOS obviously supports that, and that should be the main functionality of this event, we expect it to work, thus the bug.... Sorry for my tone, but this was also been the issue with older Expo versions, but then at least it worked on some Android devices, now it doesn't work at all. I think it would be to late for us to wait version Expo 40.
I'm just trying to see if my issue is specific to me or not so that maybe we can file a new issue and get a reproducible demo for the Expo team.
To be clear, I'm assuming it will always be broken through the Expo client, I don't really care about that working since it's not what users use. Branch also doesn't work through Expo client so I'm kind of already used to these quirks. π
If addNotificationResponseReceivedListener does not work for you in Standalone Managed 39.0 Android no matter where you put the listener, can you put a like on this comment?
Also, can anyone tell me, what could cause a listener to get installed to be uninstalled...perhaps there is some code running later that is invalidating it...like it's overwriting it or something, idk. I'm going to work all day today to try to get it either working or a reproducible demo for the Expo team.
After 20+ hours on this problem I think I was able to track down the issue but I tried hard to create a MCVE but could not do it :(
My app has a logged out mode and logged in mode. When I was logged out, I noticed that Android would read the notification from a killed state. When I was logged in, it wouldn't. This means I was doing something further in those components that interfered with the addNotificationResponseReceivedListener handler that I initialized literally at the very entrance to my application.
After turning things off and on and re-building...I eventually commented out this block of code:
Location.startLocationUpdatesAsync(backgroundLocationUpdateTaskName, {
// Lowest = 3KM, Low = 1 KM, Balanced = 100M, High = 10M, Highest = 1M
// We use High, which is accurate to within 10m, should be enough for this app, since we don't do maps.
accuracy: LocationAccuracy.High,
timeInterval: 60000, // in ms
// Receive updates only when the location has changed by at least this distance in meters
distanceInterval: 60000,
});
and voila, it started working again from a dead start consistently. This tells me that there is some interaction under the hood between startLocationUpdatesAsync and addNotificationResponseReceivedListener on standalone Android.
Trying to find a workaround, I tried adding a timeout to start the startLocationUpdatesAsync function and it worked the first time that the app updated to a new version, but afterwards if the app was killed without being able to turn off the background job (it is a background job after all), next time I open the app the "Location Icon" on Android on the top status bar is immediately on and I go back to the same problem.
Essentially, when the background location is on in my app, notifications on standalone Android do not get read from a dead start. However, in the test app I made, it did work so I understand why this is hard to debug.
The best I can do at this moment is turn off the background task when the user leaves the app so that it only runs when the app is not-killed and then when they do kill it, if they re-open it with a push notification it will work (assuming I also have the delay on starting startLocationUpdatesAsync).
It's all really messy but hopefully this can help get to the root of the problem and maybe others who are experiencing this will realize that they are also using background location and can potentially try turning it off and testing.
@milennaj @Maoravitan @coopbri @beDenz @KlasRobin - Are you guys using any background tasks on Standalone Android? If you are, are you also using React-Navigation as well since others reporting this problem are also using that library?
cc @cruzach - Do you have any thoughts on what might be going on or things I can try?
PS android.useNextNotificationsApi is set to true for me ;)
Want to mention that legacy notification was not firing event for me on sdk 39, even if declared globally.
Only expo-notifications package was working and only if addNotificationResponseReceivedListener was declared globally
@Aryk - Your discovery that removing Location.startLocationUpdatesAsync from the equation seems consistent with what I saw with my async font loading. When my app was loading fonts async before rendering my notification handler component, addNotificationResponseReceivedListener would not fire from killed state.
Once I moved that async work to after addNotificationResponseReceivedListener, it works from killed state.
@sealedHuman - that's interesting...all this tells me is that whatever is happening under the hood for addNotificationResponseReceivedListener is very flakey...seemingly un-related items are cross-interacting with it.
It seems like a pretty serious issue, because literally for any Expo users out there...notifications from a dead start on android could just stop working simply because they wanted to add some unrelated XYZ feature which gets enabled further down on bootup.
@cruzach @ide - Do you guys happen to have any idea what could be causing addNotificationResponseReceivedListener to get disabled by seemingly unrelated items down-the-line on bootup? This could maybe help me create a MCVE for you guys so we can get this solved.
@Aryk I recommend trying out the changes being introduced in https://github.com/expo/expo/pull/10811 (they're JS-only, so it should be perfectly doable in the managed workflow) and seeing if that helps. I would have to take a deeper look at expo-task-manager (Location.startLocationUpdates calls directly to the task manager) before speaking on if that was having any impact on expo-notifications
@cruzach I have tried the solution introduced in #10811 . It doesn't work. I will try again disabling async font loading.
@sjchmiela I have tried both solutions in managed workflow (standalone app)
nothing seems to be working. Do you have any working demo?
@Aryk I recommend trying out the changes being introduced in #10811 (they're JS-only, so it should be perfectly doable in the managed workflow) and seeing if that helps. I would have to take a deeper look at
expo-task-manager(Location.startLocationUpdatescalls directly to the task manager) before speaking on if that was having any impact onexpo-notifications
I looked at that code...but how exactly can it help? It still calls addNotificationResponseReceivedListener and relies on that to actually run it's callback.
What the hook ensures is that the notification response listener gets registered as early as it can (in the global scope of the app) and not as a result of any component code which is one of the problems people have run into in the past.
I'm not yet able to explain why triggering an asynchronous function in global scope would interact with adding a notification response listener without flapping arms in the air and stating imprecise possible reasons.
Regarding the fact that removing Location.startLocationUpdatesAsync and asynchronous font loading seemingly removes the issue β I'm not sure starting location updates or font loading in global scope is the way to do it (none of the examples available try to do so, for location you first need to ensure you have the right permissions, for fonts it simply doesn't make sense). Sorry for asking this again and again β are you sure the issue remains if you move the listener to global scope of the app?
@sjchmiela - Thanks for taking the time. I've mentioned it above in my essay comment ;) Yes I've tried putting this:
Notifications.addNotificationResponseReceivedListener(
response => Alert.alert(undefined, "first")
)
in the global scope at the very very very top of my App so that it's literally one of the first things running...and as I mentioned it does work! _BUT_ only if I do not call Location.startLocationUpdates at all down the line, and by down the line I mean in a component callback, it's not even in global scope.
Also, on standalone android, while the location task is on, the addNotificationResponseReceivedListener also won't receive calls from a dead start, so I need to turn it off when users kill the app.
That is why I have to essentially disable it for the first 6 seconds of my app bootup and then initialize it and only then notifications work from a dead start on standalone android.
This is why I don't understand why https://github.com/expo/expo/pull/10811 would work since it's still relying on the same call.
@sjchmiela Sorry for misleading comment about async font loading. I had a hunch that loading font taking time to initiate the app from kill mode. But it has nothing to do here.
I will try #10811 again with a fresh app. Maybe something else is preventing it to work.
I know that startLocationUpdates has event emitters and has caused problems even in the previous 38 release so my hunch is that there is some collison with the events there and that it's still not 100% stable.
When you mentioned about the async font loading, I was suspicious that it was actually related because doesn't really do anything with event emitters that could interrupt receiving the notifications.
is there a useInitialNotificationResponse class components example?
new bug? now addNotificationResponseReceivedListener and addNotificationReceivedListener not work at all in Android not background and not foreground and not killed... π€―
Hi @sjchmiela, as @Aryk I have refactored the code and put addNotificationResponseReceivedListener at the top of App with appropriate navigation to modals when notifications is received. I can confirm that event is fired only when app is running in foreground, not when app process is not running. This happens on app that is available on Google Play store, and has "useNextNotificationsApi": true in app.json. Phone that is used for testing is Motorola moto g pro. Location is not used in our app.
If this helps this is App.tsx of our app:
import React, { useState, useEffect } from "react";
import { StatusBar, StyleSheet } from "react-native";
import { AppearanceProvider } from "react-native-appearance";
import { Provider } from "react-redux";
import { Container, Root } from "native-base";
import { store } from "./store";
import * as Font from "expo-font";
import { AppLoading } from "expo";
import { Ionicons } from "@expo/vector-icons";
import AppNavigator from "./navigation/AppNavigator";
import interceptors from "./interceptors";
import * as Notifications from "expo-notifications";
import moment from "moment";
import {
CloseMonthWarningTag,
CloseMonthReminderTag,
dateFormat,
} from "./constants/constants";
import { navigationRef } from "./RootNavigation";
import * as RootNavigation from "./RootNavigation.js";
export default function App(props) {
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: false,
shouldSetBadge: true,
}),
});
useEffect(() => {
const subscription = Notifications.addNotificationResponseReceivedListener(
(response) => {
if (response.notification !== null) {
let tag = response.notification.request.content.data.tag;
tag === CloseMonthWarningTag
? RootNavigation.navigate("CloseMonthWarning", {
date: moment().format(dateFormat),
})
: tag === CloseMonthReminderTag
? RootNavigation.navigate("CloseMonth")
: RootNavigation.navigate("Hours", {
currentDate: moment().format(dateFormat),
});
}
}
);
return () => {
subscription.remove();
};
}, []);
interceptors.setupInterceptors();
const [isLoadingComplete, setLoadingComplete] = useState(false);
if (!isLoadingComplete && !props.skipLoadingScreen) {
return (
onError={handleLoadingError}
onFinish={() => handleFinishLoading(setLoadingComplete)}
/>
);
} else {
return (
);
}
}
async function loadResourcesAsync() {
await Promise.all([
Font.loadAsync({
Ubuntu: require("./assets/fonts/Ubuntu-Regular.ttf"),
Bold: require("./assets/fonts/Ubuntu-Bold.ttf"),
Roboto_medium: require("native-base/Fonts/Roboto_medium.ttf"),
...Ionicons.font,
}),
]);
}
function handleLoadingError(error) {
console.warn(error);
}
function handleFinishLoading(setLoadingComplete) {
setLoadingComplete(true);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#EEEEEE",
height: "100%",
},
});
I don't see what else we can do to make it work?
Hello guys, I'm facing the same issue: foreground notifications works perfectly on android, but addNotificationResponseReceivedListener doesn't emit when the app is closed or killed. I'm also using the expo SDK 39
@milennaj @LucasPMM - Can you guys comment if you are using background tasks like startLocationUpdatesAsync? If you are, try commenting it out and seeing if starts working.
@milennaj you are still putting the listener within your component and in a useEffect. This is the confirmed bug, reading the discussion above the potential solution they are proposing is to initiate the listener outside the component.
Did as this example showed (with a class-based App component instead of a functional one) and using this navigation technique (because I needed to navigate to some screens when opening notifications) but got no luck either :(
Using SDK 38 and running a built .apk; received notifications in every scenario, but could handle them as I wanted to only when app is on the foreground or background (not working with the app closed).
I met this issue at Android using Expo SDK 39.0.0 with FCM. Solved using work around from above comment.
Steps of my issue:
https://github.com/expo/expo/issues/9866#issuecomment-715486316
workaround -> useLayoutEffect instead of useEffect
I have try LegacyNotifications.addListener, class component, useLayoutEffect, top level, all does not work when app is killed.
I am using sdk39.
I have set useNextNotificationsApi to true.
A hint, when tap a killed expo notification, then it open the expo client. the console show this "Finished building JavaScript bundle in 276ms." why it rebuild the bundle?
As sdk40 have come out, does this issue resolved?
It is resolved. Use the new hook useLastNotificationResponse. You can find more details in doc -https://docs.expo.io/versions/v40.0.0/sdk/notifications/#uselastnotificationresponse-undefined--notificationresponse--null
It is resolved. Use the new hook
useLastNotificationResponse. You can find more details in doc -https://docs.expo.io/versions/v40.0.0/sdk/notifications/#uselastnotificationresponse-undefined--notificationresponse--null
I am trying to implement the example but with no success.
This is part of my code:
const lastNotificationResponse = Notifications.useLastNotificationResponse();
useEffect(() => {
if (lastNotificationResponse && lastNotificationResponse.actionIdentifier === Notifications.DEFAULT_ACTION_IDENTIFIER) {
handlePush(lastNotificationResponse);
}
}, [lastNotificationResponse]);
const handlePush = async ({ notification }: any) => {
// ...more code <<<<< --------- it never reaches to this point when the app has been killed.
}
Am I doing something wrong?
Thanks
It is resolved. Use the new hook
useLastNotificationResponse. You can find more details in doc -https://docs.expo.io/versions/v40.0.0/sdk/notifications/#uselastnotificationresponse-undefined--notificationresponse--null
Just tested the issue is still there.
I still have to use exp.notification to get launch notification on iOS and addNotificationResponseReceivedListener outside any component on Android.
Any tips?
@maurohmartinez I am getting it to work with your exact code (only importing my async function where I destructure notification). Is your lastNotificationResponse correctly identified on app start?
I have my hook as the first hook being fired, i.e.:
export default function App() {
const lastNotificationResponse = Notifications.useLastNotificationResponse();
@alexandrius try if your hook is the first thing being initialized on app start? Works fine for me, had to do a bit of a workaround to get the navigation container to properly handle the incoming notification link as it is received before the navigationcontainer has time to initialize.
@maurohmartinez I am getting it to work with your exact code (only importing my async function where I destructure notification). Is your lastNotificationResponse correctly identified on app start?
I have my hook as the first hook being fired, i.e.:
export default function App() { const lastNotificationResponse = Notifications.useLastNotificationResponse();@alexandrius try if your hook is the first thing being initialized on app start? Works fine for me, had to do a bit of a workaround to get the navigation container to properly handle the incoming notification link as it is received before the navigationcontainer has time to initialize.
My mistake... it works on Android (was trying on iOS). In my case, it doesn't even need to be placed right after export default function App() { but again, it might be just in my case.
Thanks!
It is resolved. Use the new hook
useLastNotificationResponse. You can find more details in doc -https://docs.expo.io/versions/v40.0.0/sdk/notifications/#uselastnotificationresponse-undefined--notificationresponse--null
This is not completed resolved if you are using Location.startLocationUpdates as well. The addNotificationResponseReceivedListener from useLastNotificationResponse somehow interacts and causes an issue from opening a notification from a dead-start of the app.
See my comment above: https://github.com/expo/expo/issues/9866#issuecomment-724829714
Perhaps it make sense to split this out into a separate issue at this point? @cruzach
It is resolved. Use the new hook
useLastNotificationResponse. You can find more details in doc -https://docs.expo.io/versions/v40.0.0/sdk/notifications/#uselastnotificationresponse-undefined--notificationresponse--null
Thanks a lot. Can confirm that it is now working on android with the new hook. π
It is resolved. Use the new hook
useLastNotificationResponse. You can find more details in doc -https://docs.expo.io/versions/v40.0.0/sdk/notifications/#uselastnotificationresponse-undefined--notificationresponse--null
I confirmed that Android works now, but ios 12 does not work.
any other guys have the same issue on ios?
Hi @imhazige, I had issues on iOS 14, and still on Android for some reason (I think it had to do with the navigation mounting or something). I know this is not an ideal solution, but I switched to OneSignal for our app and it's been working great on both platforms (minus the typical FCM/APNs pitfalls, particularly slightly delayed notifications). This may be considered off-topic for the thread, but wanted to mention my success story just to indicate it as an option for you. Keep in mind it is a library with native bindings, so the Expo bare workflow is required if you choose to go that route.
I have no doubt the Expo notifications API will continue to improve over time, but I did not have time to wait, unfortunately.
Hi @imhazige, I had issues on iOS 14, and still on Android for some reason (I think it had to do with the navigation mounting or something). I know this is not an ideal solution, but I switched to OneSignal for our app and it's been working great on both platforms (minus the typical FCM/APNs pitfalls, particularly slightly delayed notifications). This may be considered off-topic for the thread, but wanted to mention my success story just to indicate it as an option for you. Keep in mind it is a library with native bindings, so the Expo bare workflow is required if you choose to go that route.
I have no doubt the Expo notifications API will continue to improve over time, but I did not have time to wait, unfortunately.
@coopbri
Thank you for the response.
I am using SDK40 and it works on android, for ios it seems to have this issue (https://github.com/expo/expo/issues/11343) need to be fixed.
I have no choice for now as I have to bind to expo managed flow. Onesignal is better choice if I can use bareflow.
Issue has been closed for fixes have been merged, please allow up to 24 hours for them to be available when you run expo build:ios (it's pretty late where I am and although I believe there will be no problems when we deploy to production I want to be a responsible citizen and not deploy and go to sleep).
As a foretaste and to some degree proof let me share with you this video β https://www.dropbox.com/s/u2ih7umzt1zbxbp/RPReplay_Final1608160452.mp4?dl=0 π
Fix has been deployed to production Turtle builders! π All iOS apps built after December 17, 2020, 15:45 UTC will have fixes included and should not longer suffer from this problem.
This being said, let us know if this or similar problem ever rises again!
Most helpful comment
Hi @cruzach,
Works when app is in background, but not when the app is killed.
The issue still persist on Android with both SDK 38 and SDK 39 in a managed workflow.
I try to move out
addNotificationResponseReceivedListeneroutside of my component as suggested, but it doesn't work.Thanks