Expo Push Notifications in Production on Android

React Native

29 Jan 2021 | 5 minute read

Lately, I've been working on a React Native project using Expo and I ran into some issues with the push notifications in production on Android. Everything worked great during development and in production for iOS but Android simply wouldn't send any notifications or register the expo push token.

After some investigation, it turned out that one needs to configure Firebase Cloud Messaging to enable push notifications on Android devices while no configuration is required for iOS devices. Unfortunately, this was not presented clearly.

To make things easier for you if you're experiencing the same issue, here's how I solved it.

Setup Firebase Cloud Messaging

Follow the steps found at https://github.com/expo/expo/blob/master/docs/pages/push-notifications/using-fcm.md.

Register the user's expo push token

To register the user's expo push token, I used the following hook.

import * as React from 'react';
import { Platform } from 'react-native';
import Constants from 'expo-constants';
import * as Notifications from 'expo-notifications';
import fishyApi from '../api/fishyApi';

export default function useNotification() {
  const [token, setToken] = React.useState<String | undefined>(undefined);

  React.useEffect(() => {
    const requestNotificationPermissionAsync = async () => {
      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;
        }
        const token = (await Notifications.getExpoPushTokenAsync()).data;
        await fishyApi().createExpoNotificationTokenViewSet({
          token: token,
        });
        setToken(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',
        });
      }
    };

    requestNotificationPermissionAsync();
  }, []);

  return token;
}

This hook is used on the landing screen after the user signs in and the expo push token is pushed to the backend.

Send notifications

Either send notifications using the HTTP/2 API or the server SDKs.