I am on a managed workflow app with expo 47. I am using eas-cli/3.5.2 at the moment. On the EAS build I am creating I am running the following:
eas build --profile preview --message 'testing notifications'
I am trying to add push notifications to my project. When I trigger them on the expo go app on my device, they work exactly as expected. I am able to trigger them with the default method that is mentioned in the documentation. However, they have an odd behavior when i trigger the second example below from the EAS build version of the app. They trigger expo’s notification, not the one from the app.
This is the function I am using to trigger the notification on both instances.
export async function sendPushNotification(token, title, body, path, id) {
const message = {
to: token,
sound: "default",
title,
body,
data: { url: `myapp://${path}${id}` },
};
await fetch("https://exp.host/--/api/v2/push/send", {
method: "POST",
headers: {
Accept: "application/json",
"Accept-encoding": "gzip, deflate",
"Content-Type": "application/json",
},
body: JSON.stringify(message),
});
}
This is the code I am using to register the token (the first time, and it is present during the button push to send the current ussr a notification (the first instance here). But it is not present on the second instance because it is supposed to go to another user, not the user that triggers the notification. I feel like this may have something to do with my issue.
export async function registerForPushNotificationsAsync() {
let token;
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;
} else {
alert("Must use physical device for Push Notifications");
}
return token;
}
Next we take a look at the default code from the documentation. This code works on both in the expo app (on my device) and the EAS build version of the app. The deep linking is working, and when I click the button to send the notification it works. The expo token that is printed out also displays. On the expo version, it launches an expo notification with the expo icon, and on the EAS build version it launches a notification with the icon from my app, as expected.
import { useState, useEffect, useRef } from "react";
import { Linking, View, Button, Text } from "react-native";
import * as Notifications from "expo-notifications";
import {
sendPushNotification,
registerForPushNotificationsAsync,
} from "../../helpers/notification";
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: false,
shouldSetBadge: false,
}),
});
export default function Notification() {
const [expoPushToken, setExpoPushToken] = useState("");
const notificationListener = useRef();
const responseListener = useRef();
useEffect(() => {
registerForPushNotificationsAsync().then((token) =>
setExpoPushToken(token)
);
responseListener.current =
Notifications.addNotificationResponseReceivedListener((response) => {
const linkUrl = response?.notification?.request?.content?.data?.url;
if (linkUrl) Linking.openURL(linkUrl);
});
return () => {
Notifications.removeNotificationSubscription(
notificationListener.current
);
Notifications.removeNotificationSubscription(responseListener.current);
};
}, []);
return (
<View style={{ alignItems: "center", justifyContent: "space-around" }}>
<Button
title="Press to Send Notification"
onPress={async () => {
console.log("Expo push token: ", expoPushToken);
await sendPushNotification(
expoPushToken,
"Title",
"Body",
"post/",
"0ekbrEwxFHt0l79E4Tgg" // this is a random post to link to
);
}}
/>
<Text>{expoPushToken}</Text>
</View>
);
}
However, when I try to launch a notification based on an action, in this case, a user liking a post, it works on the expo app as expected, the deep linking works and directs me to the post (on the actual EAS build version), but in the EAS build version, it triggers an expo notification, not a notification from the EAS built app. I deleted the expo app itself for testing and no notification was delivered at all. I am not asking for permission in this instance, but instead I am relying on the token I have stored in my firestore database, to trigger the notification. It is the exact same token that is being used in the first (default documentation) instance because I am liking a post by the same user that is using the app. And it works perfectly in the expo app itself. But it is not triggering the notification from the EAS build version of the app.
There is a lot of code here so I am showing the relative pieces in hopes that someone can help me figure this out. Some of the code has been omitted for brevity.
import { useRef, useEffect } from "react"
import { Linking, Text, View, Image } from "react-native";
import { sendPushNotification } from "../../helpers/notification";
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: false,
shouldSetBadge: false,
}),
});
const MyComponent = () => {
const notificationListener = useRef();
const responseListener = useRef();
useEffect(() => {
responseListener.current =
Notifications.addNotificationResponseReceivedListener((response) => {
const linkUrl = response?.notification?.request?.content?.data?.url;
if (linkUrl) Linking.openURL(linkUrl);
});
return () => {
Notifications.removeNotificationSubscription(
notificationListener.current
);
Notifications.removeNotificationSubscription(responseListener.current);
};
}, []);
return (
<TouchableOpacity
onPress={async () =>
await addLike(postId, uid, isLiked).then((res) => {
if (isLiked) {
setIsLiked(false);
setNumLikes(numLikes--);
} else {
setIsLiked(true);
setNumLikes(numLikes++);
// call the async function to trigger notification //
(async () => {
try {
await db.collection("users").doc(userRef).get()
.then((doc) => {
const token = doc?.data().notificationsToken;
if (token) {
setExpoPushToken(token);
(async () => {
await sendPushNotification(
token, /
"New Like!",
`${username} liked your post`,
"post/",
postId
);
})();
}
});
} catch (error) { console.warn(error) }
})();
}
})
}
style={[postStyles.icon]}
>
<Image
source={isLiked ? likeImage : unlikeImage}
style={{ width: 20, height: 16 }}
/>
</TouchableOpacity>
<View>
{/* This displays the exact same token as the one from the demo because I am clicking a post made by the test user that has the same token */}
<Text>{expoPushToken}</Text>
</View>
)
}
I know this a lot of code but I really hope someone has some insight as to strange behavior I am experiencing here. It is baffling me that the the same exact call with the same token is working perfectly fine from the first code and yet it doesn’t work on the second. Please Please help.