DEV Community

loading...
Cover image for Minimalist Approach to send Push Notifications with Expo

Minimalist Approach to send Push Notifications with Expo

José Donato
・4 min read

Small tutorial to help you understand and send push notifications with Expo.

I developed a simple open source web application that helps sending push notifications with Expo. React and Material-UI were used and all the source code is available on github. Live demo: https://expo-notifications-tool.now.sh/.

Before diving into the web application, we need to understand push notifications and setup the backend server.

Expo backend image

Reading expo documentation we need two main things to use Expo Push Notifications:

  1. Getting a user's Expo Push Token: We achieve this by calling an endpoint (/token) on our server (explained below) when the expo mobile app is launched.
  2. Calling Expo's Push API with the token when you want to send a notification: It was to facilitate the process in this step that I developed the web app. This web app calls another endpoint (/message) of the backend server and the backend server sends the notifications for all the devices.

The backend developed with NodeJS and expo-server-sdk-node is running in https://glitch.com/~easy-soup. Note that we need the endpoint available in a public URL to send the notifications. Glitch (❤️) makes this as simple as it gets.

const express = require("express");
const { Expo } = require("expo-server-sdk");
const app = express();
const expo = new Expo();
const cors = require("cors");

app.use(cors());
let savedPushTokens = [];
const PORT_NUMBER = 3000;

const handlePushTokens = ({ title, body }) => {
  let notifications = [];
  for (let pushToken of savedPushTokens) {
    if (!Expo.isExpoPushToken(pushToken)) {
      console.error(`Push token ${pushToken} is not a valid Expo push token`);
      continue;
    }

    notifications.push({
      to: pushToken,
      sound: "default",
      title: title,
      body: body,
      data: { body }
    });
  }

  let chunks = expo.chunkPushNotifications(notifications);

  (async () => {
    for (let chunk of chunks) {
      try {
        let receipts = await expo.sendPushNotificationsAsync(chunk);
        console.log(receipts);
      } catch (error) {
        console.error(error);
      }
    }
  })();
};

const saveToken = token => {
  console.log(token, savedPushTokens);
  const exists = savedPushTokens.find(t => t === token);
  if (!exists) {
    savedPushTokens.push(token);
  }
};

app.use(express.json());

app.get("/", (req, res) => {
  res.send("Push Notification Server Running");
});

app.post("/token", (req, res) => {
  saveToken(req.body.token.value);
  console.log(`Received push token, ${req.body.token.value}`);
  res.send(`Received push token, ${req.body.token.value}`);
});

app.post("/message", (req, res) => {
  handlePushTokens(req.body);
  console.log(`Received message, with title: ${req.body.title}`);
  res.send(`Received message, with title: ${req.body.title}`);
});

app.listen(PORT_NUMBER, () => {
  console.log(`Server Online on Port ${PORT_NUMBER}`);
});
Enter fullscreen mode Exit fullscreen mode

Basically, on the server we have two endpoints listening to POST requests:

  1. https://easy-soup.glitch.me/token
  2. https://easy-soup.glitch.me/message

The first one receives and saves the tokens sent from each device running the expo app.
The second one handles the requests that will be received from the expo notifications tool, i.e., receives the title and body of the notification from the web app and sends the notification with this content for each device.

Now that we have the endpoints up and running on the URL https://easy-soup.glitch.me we can set it up on expo mobile app and expo notification tool.

Configuring expo mobile app to register the tokens:

First we need to create the function that will push the token when the app is started. Note that the PUSH_ENDPOINT contains the URL of the glitch endpoint.

//registerForPushNotifications.js
import { Notifications } from 'expo';
import * as Permissions from 'expo-permissions';

const PUSH_ENDPOINT = 'https://easy-soup.glitch.me/token';

const registerForPushNotifications = async () => {
  const { status } = await Permissions.askAsync(Permissions.NOTIFICATIONS);
  if (status !== 'granted') {
    alert('No notification permissions!');
    return;
  }

  // Get the token that identifies this device
  let token = await Notifications.getExpoPushTokenAsync();

  // POST the token to your backend server from where you can retrieve it to send push notifications.
  return fetch(PUSH_ENDPOINT, {
    method: 'POST',
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      token: {
        value: token,
      }
    }),
  });
}
export default registerForPushNotifications;
Enter fullscreen mode Exit fullscreen mode

After, we need to call the function we created when the application mounts.

//App.js
import React, {useEffect} from 'react';
import { StyleSheet, Text, View } from 'react-native';
import registerForPushNotifications from './registerForPushNotifications';


const App = () => {
  useEffect(() => {
    registerForPushNotifications()
  }, []);
  return (
    <View style={styles.container}>
      <Text>Notifications Example</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

export default App;
Enter fullscreen mode Exit fullscreen mode

Snack containing the application code (also available in the github repo).

When the application is started and mounts, the glitch endpoint will be called and the token will be saved in the glitch server. The following image is a log in the glitch server telling that received the push token from the expo app.

token registered

Now we are ready to launch the expo notifications tool and start sending some notifications.

In the web app we just need to input the title and the body that we want to appear in the notification.

Expo notification tool

After we press the "send notifications" button, the web app will send a post request to the glitch endpoint /message with the title and the body. The glitch server goes through all the tokens saved and sends the notification for each one.

If everything works as expected, the notification will be received in all mobile phones that launched the expo application.

Android notification confirmed

Please note that the server code hosted on glitch is minimalist and needs some improvement to be used in real applications.
I tried to make it as simple as possible because the main goal is to focus on how to send the notifications (with the web app tool) and not on how the tokens are stored.

It was my first "tutorial", hope you guys like it and help me improve it 😀

Discussion (9)

Collapse
teftef profile image
Atef Boutara

Bro u literally saved my ass with this i swear, I love u XD

Collapse
rnavedojr profile image
codingimages

That's cool thanks. I am wondering how to change the Expo logo and name in the notification banner.

Collapse
josedonato profile image
José Donato Author

hello, thanks for reading.
the documentation explain how to customize the banner, check it here: docs.expo.io/versions/latest/sdk/n...

Collapse
idode_k profile image
spreadsheet papi

this was very helpful in getting push notifications up and running for my react-native app. thank you!

Collapse
josedonato profile image
José Donato Author

glad it helped you!

Collapse
yeukfei02 profile image
Donald Wu

Thanks for sharing!

Collapse
josedonato profile image
José Donato Author

Hope you like it!

Collapse
kamrul91111 profile image
kamrul91111 • Edited

If anyone is using this for production android app, ensure to go through FCM setup as depicted on expo's website. Otherwise, you won't receive notifications on standalone android apps.

I was just wondering where the expo tokens are being stored? I wish to make my own server and was thinking if I need a database to store the tokens.

Collapse
atthuluriudaykumar profile image
Atthuluri-udaykumar

I tried that but I am not getting sound while notifications sent another one Is while working on expo the token will be saved in DB and after taking build the token was not saved ???.................