DEV Community

Neelesh Ranjan Jha
Neelesh Ranjan Jha

Posted on

Local Notifications using Expo

Introduction

Expo is a very useful framework for developing Android Applications.
The documentation is clear and crisp, but I observed that no good write-ups or blogs exist for, so in this post I will explain how to get Local Notifications in your app.
I was developing a Timetable management application known as Timely , which sends a notification 5 minute prior to the starting time of a class.
I spent a lot of time going through GitHub and Stack Overflow, searching for some answer to find a way to send notifications every week at a certain time.

Expo Notification

We will be using Expo Notifications since the project is built on Expo.
The best method is to obviously read the documentation provided by
Expo

Note - Notifications do not work on an emulator, so make sure to use a Physical device.

Step 1: Install Expo Notifications

First step is to install the package

expo install expo-notifications
Enter fullscreen mode Exit fullscreen mode

Step 2: Initialize the Notification Handler

import * as Notifications from "expo-notifications";

Notifications.setNotificationHandler({
  handleNotification: async () => ({
    shouldShowAlert: true,
    shouldPlaySound: true,
    shouldSetBadge: true,
  }),
});
Enter fullscreen mode Exit fullscreen mode

This will enable the notifications for the app.
This can be done in your entry point file like App.js or in a separate file, or you can even use Context API.

Now, how expo notifications work is that we create a Notification which is allotted a Unique ID, which can be used for deleting it later on. Every Push Notification is allotted a push token ID.

Step 3: Writing the Notifications function

This function adds the notification listener and subscriber and all the necessary things needed for getting Local notifications for your Expo App.

export default function Notification() {
  const [expoPushToken, setExpoPushToken] = useState("");
  const [notification, setNotification] = useState(false);
  const notificationListener = useRef();
  const responseListener = useRef();

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

    notificationListener.current =
      Notifications.addNotificationReceivedListener((notification) => {
        setNotification(notification);
      });

    responseListener.current =
      Notifications.addNotificationResponseReceivedListener((response) => {
        console.log(response);
      });

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

  return (
    null
  );
}
Enter fullscreen mode Exit fullscreen mode

This code can be used as it is for most projects.

Step 4: Schedule Notification function

This will be called to schedule a notification. Since I was developing a Timetable Organizer app, therefore the notifications require the day of the week, time in hours and minutes and other info to be displayed in the notification.

export async function schedulePushNotification(
  className,
  slot,
  type,
  time,
  day
) {
  time = new Date(time.getTime() - 5 * 60000);
  var days = [
    "Sunday",
    "Monday",
    "Tuesday",
    "Wednesday",
    "Thursday",
    "Friday",
    "Saturday",
  ];
  const weekday = days.indexOf(day) + 1;
  const hours = time.getHours();
  const minutes = time.getMinutes();
  const id = await Notifications.scheduleNotificationAsync({
    content: {
      title: className + " " + type,
      body: slot,
      // sound: 'default',
    },
    trigger: {
      weekday: weekday,
      hour: hours,
      minute: minutes,
      repeats: true,
    },
  });
  console.log("notif id on scheduling",id)
  return id;
}
Enter fullscreen mode Exit fullscreen mode

The things you put up inside content will be the things shown to you in the notification.
The trigger object contains the necessary trigger conditions.
You can find more on here

Step 5: Register Push Notification Function

This function again can be used as it is, as it asks for permissions from the user to send the notification and registers the notification.

async function registerForPushNotificationsAsync() {
  let token;
  if (Constants.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],
      sound: true,
      lightColor: "#FF231F7C",
      lockscreenVisibility: Notifications.AndroidNotificationVisibility.PUBLIC,
      bypassDnd: true,
    });
  }

  return token;
}
Enter fullscreen mode Exit fullscreen mode

Inside the condition check for Android device, we can specify the various things we want for the notification like sound true or false or the vibration pattern, whether to bypass DND, etc which can also be found on the documentation provided for Expo Notifications.

Step 6: Cancelling Notifications

Assume that a user created a reminder for a class but later on want to switch it off. If we don't have this function, the user, even after deleting the reminder, would get the notifications forever as notification are registered with the device itself. (Probably wipe data and cache would work then) so this function will enable us to cancel any notification if we give it the notification ID generated on creating a notification.

export async function cancelNotification(notifId){
  await Notifications.cancelScheduledNotificationAsync(notifId);
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

Now we can call the create notification function or cancel notification function whenever we need to do so.
I will link the GitHub for the whole code of the app. Feel free to check it out and send any PR for improvements!
Also, I would be glad if you could suggest improvements to this post as well as the code for this.
Thank you!

GitHub Repo link for reference

Discussion (1)

Collapse
souravpradhan980 profile image
Sourav Pradhan

Expo local notification not working in android when time format 12 hour Format
in 12 hour is working fine. Sir what is the issue