Expo Notification works great in expo app, but has issue in eas build on ios

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.

Ok well, I never heard back from anyone at expo on this and that was disappointing because I am still not 100% sure what the issue is/was. What I believe is happening and this was somewhat confirmed by a user in the notifications board on discord, but in my opinion its all up for debate is that the token I was using in expo go was somehow being mixed up and used in both the eas build version of the app and the expo go app and the expo go token was overwriting the other token. hmmm… ?? maybe ??

After spending almost a week building and testing and building and testing and wasting countless hours trying to make heads or tails of all of this, I tried out Native Notify. https://nativenotify.com/

And what had taken me 2 weeks of confusion and literal heartache lol was up and running in 5 minutes. No joke. Also, as I got deeper into the weeds with this specific issue again, even with Native Notify sending the notifications, when I built my preview build, the notifications continued to come through the expo app and not the eas built app on my machine. So, I was freaking out again and TJ, who makes the Native Notify service was extremely responsive and helpful in working the the issues with me. What a relief!

But ultimately, I would love confirmation from anyone on this, and I posted the question multiple times on discord with no response, but it seems to me that in ad hoc testing mode, where you are using internal testers before the app ever gets to TestFlight, you have to ignore apple setup altogether. What I was able to find out was that if I didn’t set up the notifications through apple’s developer setup (in native notify) and just let expo handle it, the same way you would if you were testing from the expo start command, the notifications are working great for my users off of my eas built app. I haven’t tested this theory without utilizing native notify because I was so delighted by the functionality and team playe attitude of the developer, that I am sticking with it untiil it becomes cost prohibitive (ie we get too many users or something like that)

If you have this situation though, make sure to send it to another ad hoc user that does not have the expo go app on their machine. The notifications apparently just don’t work for me, the developer who uses expo to test out the app on my own iphone. They work for my internal test users like normal.

i got same issue when i tested FMC Push notification on Expo Go App, it works fine but when i build apk by using eas its not working!!