I'm working on a React Native app and scheduling a notification, the notification arrive properly, even when the app is closed/killed. But addNotificationResponseReceivedListener() function only executes the logic when the app is in the foreground or background, but when the app is closed it only opens the app.
For now I'm using this dummy app to emulate what is happening in my app.
This is the code I have in the App.js
import * as Device from 'expo-device';
import * as Notifications from 'expo-notifications';
import React, { useState, useEffect, useRef } from 'react';
import { Text, View, Button, Platform } from 'react-native';
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: false,
shouldSetBadge: false,
}),
});
export default function App() {
const [expoPushToken, setExpoPushToken] = useState('');
const [notification, setNotification] = useState(false);
const notificationListener = useRef();
const responseListener = useRef();
const lastNotificationResponse = Notifications.useLastNotificationResponse();
React.useEffect(() => {
if (
lastNotificationResponse &&
lastNotificationResponse.notification.request.content.data.url &&
lastNotificationResponse.actionIdentifier === Notifications.DEFAULT_ACTION_IDENTIFIER
) {
Linking.openURL(lastNotificationResponse.notification.request.content.data.url);
}
}, [lastNotificationResponse]);
useEffect(() => {
registerForPushNotificationsAsync().then(token => setExpoPushToken(token));
notificationListener.current = Notifications.addNotificationReceivedListener(notification => {
setNotification(notification);
});
responseListener.current = Notifications.addNotificationResponseReceivedListener(response => {
setNotification(response);
console.log(response, 'hemos tapped');
});
return () => {
Notifications.removeNotificationSubscription(notificationListener.current);
Notifications.removeNotificationSubscription(responseListener.current);
};
}, []);
console.log(lastNotificationResponse);
return (
<View
style={{
flex: 1,
alignItems: 'center',
justifyContent: 'space-around',
}}>
<Text>Your expo push token: {expoPushToken}</Text>
<View style={{ alignItems: 'center', justifyContent: 'center' }}>
</View>
<Button
title="Press to schedule a notification"
onPress={async () => {
await schedulePushNotification();
}}
/>
</View>
);
}
async function schedulePushNotification() {
await Notifications.scheduleNotificationAsync({
content: {
title: "You've got mail! ",
body: 'Here is the notification body',
data: { data: 'goes here' },
},
trigger: { seconds: 5 },
});
}
async function registerForPushNotificationsAsync() {
let token;
if (Platform.OS === 'android') {
await Notifications.setNotificationChannelAsync('default', {
name: 'default',
importance: Notifications.AndroidImportance.MAX,
vibrationPattern: [0, 250, 250, 250],
lightColor: '#FF231F7C',
});
}
if (Device.isDevice) {
const { status: existingStatus } = await Notifications.getPermissionsAsync();
let finalStatus = existingStatus;
if (existingStatus !== 'granted') {
const { status } = await Notifications.requestPermissionsAsync();
finalStatus = status;
}
if (finalStatus !== 'granted') {
alert('Failed to get push token for push notification!');
return;
}
token = (await Notifications.getExpoPushTokenAsync()).data;
console.log(token);
} else {
alert('Must use physical device for Push Notifications');
}
return token;
}
Any idea what's causing this?
You have to register the listener even before your App gets initialized as fast as possible. Also the NotificationAction "opensAppToForeground" has to be enabled (it is by default).
So this part:
Should be before even your App function gets initialized:
Now your response should be triggered. But still it dont works if you set opensAppToForeground to false :/