11

reading from the expo docs:

For iOS, you would be wise to handle push notifications that are received while the app is foregrounded, because otherwise the user will never see them. Notifications that arrive while the app are foregrounded on iOS do not show up in the system notification list. A common solution is to just show the notification manually. For example, if you get a message on Messenger for iOS, have the app foregrounded, but do not have that conversation open, you will see the notification slide down from the top of the screen with a custom notification UI.

What I don't understand is what is the best approach for that? is there an Expo API for showing such messages? or should I create an alert component of my own? It is not really clear from the docs.

Thanks.

superuser123
  • 955
  • 2
  • 12
  • 24
  • Yes, Expo suggests you write a "notification" component to display it when the app is in the foreground. – Dan Jan 25 '18 at 09:11

4 Answers4

4

This answer is outdated as of February 20, 2020. Please see https://stackoverflow.com/a/60344280/2441420 for how to show iOS Notification when your application is in the Foreground

There isn't an Expo API for showing those messages. You can use any 'toast' library of your choosing and display the notification message, but that should be all your code.

For example, this is how we are doing right now:

export default class HomeScreen extends React.Component {

  componentDidMount() {
    this.notificationSubscription = Notifications.addListener(
      (notification) => this.handlePushNotification(notification),
    );
  }

  handlePushNotification(notification) {
    const { navigation } = this.props;
    PushNotificationsService.handleNotification(notification, navigation);
  }

(...)

import Toast from 'react-native-root-toast';

export default class PushNotificationsService {

  static handleNotification(notification, navigation) {

    if (notification.data.screen && notification.origin === 'selected') {
      navigation.navigate(notification.data.screen);
    }
    Toast.show(notification.data.message);
  }

}

Toast libraries include:

technoplato
  • 3,293
  • 21
  • 33
sandre89
  • 5,218
  • 2
  • 43
  • 64
  • Is there no way to just pipe the notification to the iOS default behavior? Kind fo a `PushNotificationsIOS.presentLocalNotification` equivalent? – nicholas May 05 '18 at 20:57
  • 2
    @nicholas in our tests Expo's `Notifications.presentLocalNotificationAsync`does nothing unfortunately. Actually, it does one thing: it (ironically) triggers the event listener, so `this.handlePushNotification` is invoked, which creates an endless loop and freezes the app, but even if we code it in such a way to avoid the loop we can't get a local notification to display. – sandre89 Sep 27 '18 at 01:39
  • @nicholas No need to pipe anything as of v36 of Expo. Please see my answer https://stackoverflow.com/a/60344280/2441420 – technoplato Feb 21 '20 at 18:19
  • @sandre89 That workaround may still be required to disable the infinite loop, but you can show a notification with `Notifications.presentLocalNotificationAsync` by enabling the ios._displayInForeground flag in the `LocalNotification` object. Please see my answer: https://stackoverflow.com/a/60344280/2441420 – technoplato Feb 21 '20 at 18:20
3

Now you can just add that in one of your app entry point. The shouldShowAlert is what you want here

import * as Notifications from 'expo-notifications';

Notifications.setNotificationHandler({
  handleNotification: async () => ({
    shouldShowAlert: true,
    shouldPlaySound: false,
    shouldSetBadge: false,
  }),
});
EQuimper
  • 5,811
  • 8
  • 29
  • 42
  • Where should this be placed in your app? Before functional component, inside and on useEffect, outside of useEffect? – MercPls Sep 20 '21 at 15:59
  • Outside inside the App.js or index.js you can put it inside a useEffect if you like but I have no issue outside. – EQuimper Sep 20 '21 at 16:28
  • For me I am getting no notifications on foreground only. I posted my code in a stack post but it's very odd it's not working. – MercPls Sep 20 '21 at 16:32
  • Sure if you have the link so I can take a look :) – EQuimper Sep 20 '21 at 16:36
  • https://stackoverflow.com/questions/69257577/expo-push-notification-foreground-not-working Thank you! – MercPls Sep 20 '21 at 16:43
2

App.json :

{
  "expo": {
    "notification": {
      "iosDisplayInForeground": true
    }
}
saint
  • 53
  • 3
1

DEMO

I'm not sure exactly when this was added to Expo, but as of Expo version 36 is easily doable.

To show Expo Push Notifications on iOS when your app is in the foreground, please do the following:


import { Vibration } from "react-native";  
import { Notifications } from "expo";  
import * as Permissions from "expo-permissions";  
import Constants from "expo-constants";

registerForPushNotificationsAsync = async () => {                          
  if (Constants.isDevice) {                                                
    const { status: existingStatus } = await Permissions.getAsync(         
      Permissions.NOTIFICATIONS                                            
    );                                                                     
    let finalStatus = existingStatus;                                      
    if (existingStatus !== "granted") {                                    
      const { status } = await Permissions.askAsync(                       
        Permissions.NOTIFICATIONS                                          
      );                                                                   
      finalStatus = status;                                                
    }                                                                      
    if (finalStatus !== "granted") {                                       
      alert("Failed to get push token for push notification!");            
      return;                                                              
    }                                                                      
    let token = await Notifications.getExpoPushTokenAsync();
    console.log("Go to https://expo.io/notifications and copy the token below to easily send yourself a notification.");
    console.warn("Notifications on iOS (and I believe Android) ONLY WORK ON A PHYSICAL DEVICE, not a simulator or emulator!!!")               
    console.log(token);                                                    
    this.setState({ expoPushToken: token });                               
  } else {                                                                 
    alert("Must use physical device for Push Notifications");              
  }                                                                        
};                                                                         

componentDidMount() {                                                      
  this.registerForPushNotificationsAsync();                                                
  this._notificationSubscription = Notifications.addListener(              
    this._handleNotification                                               
  );                                                                       
}

_handleNotification = async notification => {                                                                                    
  if (notification.remote) {
    Vibration.vibrate();                                                  
    const notificationId = Notifications.presentLocalNotificationAsync({      
      title: "Follow @technoplato",  
      body: "To learn yourself goodly (also follow PewDiePie)",                                             
      ios: { _displayInForeground: true } // <-- HERE'S WHERE THE MAGIC HAPPENS                                
    });                                                                       
  }                                                   
};                                                                                                                                                      

Quick and Easy Sanity Check

1) Go here: https://expo.io/notifications

2) Copy the token that is output to the terminal when your application is run.

3) Open your application on iOS.

4) Send a notification to yourself from https://expo.io/notifications and observe that it shows up even when your app is foregrounded.


Notes

  • Notifications WILL NOT BE RECEIVED ON AN IOS SIMULATOR

  • Expo makes Notifications ridiculously easy. I honestly can't believe it.

No idea why displayInForeground is false by default and not more prominent in the documentation. I'll submit a PR for it if I can.

Code originally found at this Snack: https://snack.expo.io/@documentation/pushnotifications?platform=ios

LocalNotification.ios._displayInForeground found here: https://docs.expo.io/versions/v36.0.0/sdk/notifications/#localnotification

technoplato
  • 3,293
  • 21
  • 33
  • this article is about local notofications. (Push notifications are remote notifications) – Kate Jul 25 '20 at 15:58