Najeeb Ullah Khan
Najeeb Ullah Khan

Reputation: 134

Sending Expo Push Notifications to both Android and iOS devices from Reactjs Dashboard

I have an expo app which is installed on both Android and iOS devices. These apps use Firebase as a backend. I have also created a dashboard in Reactjs which is also using same Firebase as a backend.

I want to send notification to a specific user whenever i perform some event on Reactjs Dashboard. e.g: I change the order_status from "pending" to "delivered" then a firebase event changes the order_status for that user in firebase collection so i want the user to know his order has been dispatched.

How can i achieve this for both Android and iOS ?

How can i achieve this for both Android and iOS ?

SOLUTION:

App side code to setup receiving notifications:

 const [expoPushToken, setExpoPushToken] = useState('');
  const [notification, setNotification] = useState(false);
  const notificationListener = useRef();
  const responseListener = useRef();



 async function sendPushNotification(expoPushToken) {
    const message = {
      to: expoPushToken,
      sound: 'default',
      title: 'Original Title',
      body: 'And here is the body!',
      data: { someData: 'goes here' },
    };

    console.log(expoPushToken);

    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),
    });
  }

  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;
      console.log(token);
    } else {
      alert('Must use physical device for Push Notifications');
    }

    if (Platform.OS === 'android') {
      Notifications.setNotificationChannelAsync('default', {
        name: 'default',
        importance: Notifications.AndroidImportance.MAX,
        vibrationPattern: [0, 250, 250, 250],
        lightColor: '#FF231F7C',
      });
    }

    return token;
  }



useEffect(() => {
    registerForPushNotificationsAsync().then(token => setExpoPushToken(token));

    // This listener is fired whenever a notification is received while the app is foregrounded
    notificationListener.current = Notifications.addNotificationReceivedListener(notification => {
      setNotification(notification);
    });

    // This listener is fired whenever a user taps on or interacts with a notification (works when app is foregrounded, backgrounded, or killed)
    responseListener.current = Notifications.addNotificationResponseReceivedListener(response => {
      console.log(response);
    });

    return () => {
      Notifications.removeNotificationSubscription(notificationListener.current);
      Notifications.removeNotificationSubscription(responseListener.current);
    };
  }, []);

// write below code outside export App function

Notifications.setNotificationHandler({
  handleNotification: async () => ({
    shouldShowAlert: true,
    shouldPlaySound: false,
    shouldSetBadge: false,
  }),
});

npx expo install expo-notifications

From Above code you can get push Token which at first you can manually use to test notifications, then eventually you can store all user's device push tokens in some firebase DB or custom DB against their uid. Then later use these tokens to send them individual notifications.

Server Side Code:

Upvotes: 1

Views: 1167

Answers (1)

Azzy
Azzy

Reputation: 1731

Here is the code for expo nodejs sdk, check for other languages/frameworks

This is more like pseudo code

import Expo from 'expo-server-sdk';

// let sentNotificationId = //id for entry in db

   //  generating custom objects to store them in DB
   const pushNotificationsItems = [{
            // info like userId
            // sentNotificationId, entry id etc
            // data mostly needed by the app
            to: notification.token,
            notificationBody: {
              // expo push notification related info
              to: notification.token, // expo token
              title: `Some title`,
              body: message,
              data: {
               //custom data to be used in app
              }
            }
          }
   ]

 // make db entries with data you need

// checking valid expo messages
      let tickets = [];

      let notificationMessages = [];

      for (const notification of pushNotificationsItems) {

        if (!Expo.isExpoPushToken(notification.to)) {
          continue
        }

        notificationMessages.push(notification.notificationBody)

      }

// send actual notification using expo client

      const expo = new Expo({});

      const chunks = expo.chunkPushNotifications(notificationMessages);

      //console.log('message chunks', chunks)

      const resolvedPromises = await Promise.allSettled(map(chunks, async chunk => {

        const ticketChunks = await expo.sendPushNotificationsAsync(chunk);

        tickets.push(...ticketChunks)

      }));


// saving the response if needed
      if (tickets.length) {
        const mappedTickets = map(tickets, t => {

          return {
            data: t,
            notificationSentId: sentNotificationId,
            organisationId,
            createdAt: getCurrentUTCISOString() || '',
          }

        })

        await this.prisma.notificationResponse.createMany({
          data: [...mappedTickets]
        })
      }

Hope it helps you in some way

Upvotes: 0

Related Questions