React Native Push Notifications

See Refactored Push Notifications to get the update. Hey, I said I make mistakes, right?

The most recent feature we have been charged to add to the Replay FX application for the Replay FX convention this summer is push notifications. In the app, convention goers are able to save favorite events locally so they can have their own tailored schedule. We wanted a push notification for them that would let them know when an event they had ‘favorited’ was coming up in fifteen minutes.

We chose the package “react-native-push-notification,” so that we could configure local notifications on both IOS and Android. I watched this helpful video to get started. There are several files to change in Android, and you can easily follow along with the video or use the docs. I did not work on the IOS side, but my colleague Cray configured that in XCode. He had used something similar when he did a code test building a chatbot.

So, we started with a separate file that has State. It has to have “state” because it needs to be updated based on time and the current app state. Cray first had a notification sending based on intervals just as in the video. To render the notification, he imported the component to the item piece of our list view and included it inside the view like this:

Screen Shot 2017-04-28 at 1.52.13 PM

Now that he had set up where and how the PushController component renders, we needed to fine tune the PushController file. Of course, import the file at the top.
import PushNotification from 'react-native-push-notification';


The following code in some kind of form needs to exist to configure the push notifications. Of course, you do not need to console.log but can do all kinds of other things with the notification object upon callback.

componentDidMount() {
  AppState.addEventListener('change', this.backgroundNotification);
    PushNotification.configure({
      onNotification: function(notification) {
         console.log('NOTIFICATION:', notification);         
      },
    });

I wanted to be able to write the code without the event listener because I feel like it just causes trouble, but the package to configure the push notifications does not seem to function without it. The only argument that I could find to pass into the event listener was “change” which is a little annoying. What if the user of the phone does not “change” anything? For example, they could have the app open, favorite an event, and not close the app or put it in the background. In that case, the notification will never fire.

I created a second listener to add to this function to render when we have an in-app notification. And, of course, we remove the listener on “componentWillUnmount.”

The functions are called on “change” — opening the app or putting the app into the background and when the function is called we have a bunch of “if” statements. The code that follows is the function that is for the background notifications. I had to create a different function to run if the appState is “active.” I tried to do an “or/||” statement and just have one function, but it did not work. The app would just crash with the “or.”


backgroundNotification(appState) {
      if (appState=='background') {
      if (this.props.item.isFavorite) {
        let favoriteDate = new Date(this.props.item.date);
        let id = (this.props.item.id).toString();

The above code, gets the date of the favorited items so that we can create a variable that has “state” to represent the date and time of 15 minutes before the event.

The code to create that variable is ugly, but it works, and I don’t know of a better way. Dates and times are very tricky in JavaScript.


this.setState({fifteenMinutesUntil: new Date(
          favoriteDate.getFullYear() +"-0"+ (favoriteDate.getMonth()+1)+"-"+(favoriteDate.getDate()+1)+"T"+this.props.item.startTime+ "-"+"03:45"
          )});

We needed to have a Platform.OS “if” statement to render the date correctly In Android, I needed to add +1 to the getDate(). For IOS, the +1 only needs to be added to the getMonth(), which is also true in Android.

Once we have that variable, we can create a notification to fire at the appropriate time. We had some trouble with notifications firing immediately if the event time had passed, so Cray created the “if” statement at the beginning of the code below to go along with the configuration of the notification.

We had to pass the id or the PushNotification.configure would create a completely new notification object each time there was an app change. In that situation, when I did not pass a specific id, and I changed the state of the app, many, many notifications would fire. By passing the id — by the way, it has to be a string — we only create one notification object and only one notification fires.

The way the notification works “under the hood” is by adding .getTime() to the date and returning the milliseconds. The getTime() function did not work if we did not create a new date here. As it is, the notification fires once at the date and time passed to date.

One little problem that I have not figured out is that when I click on the notification in the emulator it automatically opens the app. I don’t know if there will be a dismiss “x” on the screen of people with real phones. I hope so.


if(this.state.fifteenMinutesUntil >= Date.now()){
           PushNotification.localNotificationSchedule({	
            id: id,	      
            message: this.props.item.title + ' will begin in 15 minutes',
            date: new Date(this.state.fifteenMinutesUntil), 

It took me several days and lots of console.logging but it works pretty well now on the simulators. I can’t wait to see how it builds this evening in our beta. There was very little help out there — only the one video, no StackOverflows, and nothing in the docs — to work for our specific situation. I hope that this post helps you figure out local scheduled push notifications.

And, I figured it out some more important things and rewrote the code after this. See Refactored Push Notifications to get the update. Learning from mistakes, just as promised.

Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s