Skip to main content

Implementing Push Notifications (expo-notifications)

1. Requesting Notification Permissions

Permission Description Status
notifications Allows the app to receive and display push notifications. NEW

Example: Requesting Notification Permissions

import * as Notifications from 'expo-notifications';

// Request permission to show notifications
const { status } = await Notifications.requestPermissionsAsync();

if (status === 'granted') {
  console.log("Notification permission granted");
} else {
  console.log("Notification permission denied");
}
Note: On iOS, users can revoke permissions at any time from Settings. On Android, permissions are granted by default but can be revoked in app settings.

2. Getting Push Token

Property Description Example
pushToken Unique identifier for device to receive push notifications ExpoPushToken["ExponentPushToken[...]"]

Example: Request Push Token

import { Notifications } from "expo-notifications";

// Request permissions
await Notifications.requestPermissionsAsync();

// Get push token
const token = await Notifications.getExpoPushTokenAsync();
console.log(token.data);
Note: Push tokens are unique per device and app instance. They expire when the app is uninstalled or permissions are revoked.

3. Scheduling Local Notifications

Property Description Values
content.title Title of the notification string
content.body Body text of the notification string
trigger Trigger for when the notification should fire number | Date | { seconds: number; cycle?: 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly'; }
identifier Unique identifier for the notification string
sound Sound to play when notification fires true | false | string

Example: Schedule a local notification after 5 seconds

import * as Notifications from 'expo-notifications';

Notifications.scheduleNotificationAsync({
  content: {
    title: "Reminder",
    body: "Don't forget to complete your task!",
  },
  trigger: {
    seconds: 5,
  },
});

Example: Schedule a repeating daily notification

import * as Notifications from 'expo-notifications';

Notifications.scheduleNotificationAsync({
  content: {
    title: "Daily Reminder",
    body: "Time for your daily check-in.",
  },
  trigger: {
    seconds: 0,
    cycle: 'daily',
  },
});
Note: On Android, local notifications require the android.permission.POST_NOTIFICATIONS permission to be granted by the user.

4. Handling Received Notifications

Property Description Example
notification The received notification object containing data and metadata { id: '123', title: 'Hello', body: 'This is a test' }
data Custom data payload sent with the notification { userId: 'user123', action: 'openProfile' }
request Request object that includes the notification and its trigger { trigger: 'push', content: { ... } }

Example: Handling Notification in App

import { Notifications } from 'expo-notifications';

Notifications.setNotificationHandler({
  handleNotification: async (notification) => {
    const { data } = notification.request.content;
    console.log('Received notification:', notification);
    if (data && data.userId) {
      // Navigate to user profile or perform action
      return {
        shouldShowAlert: true,
        shouldPlaySound: true,
        shouldSetBadge: true
      };
    }
    return {
      shouldShowAlert: false,
      shouldPlaySound: false,
      shouldSetBadge: false
    };
  }
});
Note: The handleNotification function is called whenever a notification is received while the app is in the foreground or background. It allows you to customize how notifications are handled.

Key Points

  • handleNotification is used to define behavior when a notification is received.
  • You can control whether an alert, sound, or badge should be shown based on notification content.
  • Custom data can be used to trigger specific actions in your app.

5. Handling Notification Tap

Property Description Example
notification The notification object that was tapped { title: 'Hello', body: 'This is a tap event' }
actionIdentifier Identifier of the action that triggered the notification 'DEFAULT'

Example: Handling Notification Tap

import * as Notifications from 'expo-notifications';

Notifications.addNotificationTapEventListener((notification) => {
  console.log('Notification tapped:', notification);
});

// Example notification object
const exampleNotification = {
  title: 'Hello',
  body: 'This is a tap event',
  data: { screen: 'Home' }
};

// Simulated tap handler
console.log('Tapped notification:', exampleNotification);
Note: The tap event listener is only triggered when the app is in the foreground or background. If the app is closed, the notification will be delivered to the system tray.

6. Setting Notification Handler

Property Description Values
setNotificationHandler Function to set the notification handler async (notification) => { ... }

Example: Setting Notification Handler

import * as Notifications from 'expo-notifications';

Notifications.setNotificationHandler({
  handleNotification: async (notification) => {
    return {
      shouldShowAlert: true,
      shouldPlaySound: true,
      shouldSetBadge: true,
    };
  },
});
Note: The handler must be set before any notifications are received to ensure proper handling.

7. Setting Badge Count

Property Description Values
badge Controls the badge count displayed on the app icon number or null

Example: Setting Badge Count

import * as Notifications from 'expo-notifications';

// Set badge count to 5
Notifications.setBadgeCountAsync(5);

// Clear badge count
Notifications.setBadgeCountAsync(null);
Note: Badge count behavior varies by platform. iOS may require additional configuration in app.json.

8. Canceling Notifications

Canceling notifications in Expo is handled through the Notifications API. You can cancel individual notifications or all pending notifications.

Method Description Notes
Notifications.cancelScheduledNotificationAsync() Cancels a specific scheduled notification by ID Requires the notification ID returned from scheduling
Notifications.cancelAllScheduledNotificationsAsync() Cancels all currently scheduled notifications Useful for cleaning up before app shutdown or reset

Example: Canceling a Specific Notification

import * as Notifications from 'expo-notifications';

// Schedule a notification
const notificationId = await Notifications.scheduleNotificationAsync({
  content: {
    title: 'Scheduled Alert',
    body: 'This is a scheduled notification',
  },
  trigger: {
    seconds: 60,
  },
});

// Cancel the specific notification
await Notifications.cancelScheduledNotificationAsync(notificationId);

Example: Cancel All Scheduled Notifications

import * as Notifications from 'expo-notifications';

// Cancel all scheduled notifications
await Notifications.cancelAllScheduledNotificationsAsync();

9. Creating Android Channels

Channel ID Description Notes
default Default notification channel for the app Automatically created if not present
low_priority Used for low-priority notifications May be grouped or suppressed by system
high_priority Used for high-priority notifications Always shown, even when device is in Do Not Disturb mode

Example: Creating a Custom Channel

import * as Notifications from 'expo-notifications';

Notifications.createChannelAsync('my-channel', {
  name: 'My Custom Channel',
  description: 'Used for important notifications',
  sound: 'default',
  priority: 'high',
  vibrate: [200, 100, 200],
});
Note: Channel IDs must be unique within the app and cannot exceed 120 characters.
Warning: On Android 8.0 (API level 26) and above, notification channels are required for all notifications.

10. Customizing Notification Sound

Property Values Description
sound string or false Sound file to play when notification is received. Can be a filename in the app bundle or false to disable sound.

Example: Setting Custom Sound

import * as Notifications from 'expo-notifications';

Notifications.setNotificationSoundAsync('custom_sound.mp3');
Note: Sound files must be included in the app bundle and are supported on iOS and Android.

11. Using Rich Notifications

Property Values Description
title string The title of the notification
body string The body text of the notification
data object Custom data to pass with the notification
sound boolean | string Whether to play a sound or name of sound file
badge number Badge count to display on app icon
icon string URL or local path to icon image
image string URL or local path to image to display in notification
channelId string ID of the notification channel (Android)

Example: Rich Notification with Image

import * as Notifications from 'expo-notifications';

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

const notification = {
  title: 'New Message',
  body: 'You have a new message from Alex.',
  data: { messageId: '12345' },
  sound: true,
  badge: 1,
  image: 'https://example.com/image.jpg',
};

await Notifications.scheduleNotificationAsync({
  content: notification,
  trigger: null,
});
Note: On Android, rich notifications require a notification channel to be configured. The channelId must reference an existing channel created with Notifications.createChannelAsync.
Warning: Image assets must be accessible via a public URL or included in the app bundle. Local file paths are not supported for rich notification images.

12. Grouping Notifications

Grouping notifications allows you to combine multiple notifications into a single grouped notification, which can improve user experience by reducing clutter and providing better organization.

Property Description Values Notes
groupId Unique identifier for the group string Required to group notifications together
summaryArgument Summary text for grouped notifications string Used in the summary of grouped notifications
groupSummary Whether to show a group summary true | false Defaults to false

Example: Creating Grouped Notifications

import * as Notifications from 'expo-notifications';

Notifications.scheduleNotificationAsync({
  content: {
    title: 'New Message',
    body: 'You have a new message',
    groupId: 'messages-group',
    summaryArgument: '2 new messages',
  },
  trigger: null,
});
Note: Grouped notifications are supported on both iOS and Android, but behavior may vary depending on the platform's notification center settings.

Was this article helpful?