Ionic Push example supporting State Changes

This post is more than 2 years old.

Please note that I'm writing this blog post while Ionic Push is still in Alpha. Everything I discuss here may change before 1.0 is released. Use the following code with caution. One of the more interesting features of Ionic's Push feature is the ability to recognize a push message with state data. You can craft a push packet that not only includes a state value but state params as well. This is discussed in the FAQ:

I want my app to open to a specific state when I receive a notification. In addition to handling this in the onNotification function described here, you can specify which $state a notification should open your app to using the push payload. Below is an example JSON object highlighting this.
{
  "tokens":["1f0ab62df8b5c672653dea8b01d1bab4dc1b15da93f99216b5ba0f621692a89f"],
  "notification": {
    "alert": "Basic push!",
    "ios":{
      "priority": 10,
      "badge":2,
      "payload":{ "$state": "about", "$stateParams": "{\"id\": 1}" }
    }
  }
}

This works well, but I ran into a few gotchas while playing with it so I thought I'd write up a quick demo of it to help others. For my demo, I created a new Ionic project using the Tabs default. I then followed the directions in the quick start to get Push setup. One thing that may trip you up right away is that you have to ensure your application always runs the push registration call. The quick start guide has you build a demo where registration is only run when a button is pushed. In some cases, that may make sense. You may not always want to register for push notifications. Most likely though you will. So to start off, here is my modified run() block from app.js that includes push registration.

.run(function($ionicPlatform, $ionicPush, $state) {
  $ionicPlatform.ready(function() {
    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
    // for form inputs)
    if (window.cordova && window.cordova.plugins && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    }
    if (window.StatusBar) {
      // org.apache.cordova.statusbar required
      StatusBar.styleLightContent();
    }
    
    $ionicPush.register({
        canShowAlert: false, //Can pushes show an alert on your screen?
        canSetBadge: true, //Can pushes update app icon badges?
        canPlaySound: true, //Can notifications play a sound?
        canRunActionsOnWake: true, //Can run actions outside the app,
        onNotification: function(notification) {
          // Handle new push notifications here
          console.log(notification);
          
          return true;
        }
      });
         
    
  });
})

I also want to point out two important settings. First, you probably want canShowAlert to be false. If not, then every notification will fire an alert in your app. Most likely your app will respond to notifications in different ways. Sometimes with dialogs, sometimes not, but probably not always one way or the other. Secondly, to actually enable "respond to state so and so", you want to set canRunActionsOnWake to true.

Cool - so almost there. I then create a Push notification via Curl that included the state info. The Tags application includes a state called tags.chat, so I decided to use that as my 'target':

curl -u appkeyThingy: -H "Content-Type: application/json" -H "X-Ionic-Application-Id: 6aef0d7b" https://push.ionic.io/api/v1/push -d '{"tokens": ["a device token"],"notification":{"alert":"ray","ios":{"payload":{"$state":"tab.chats"}}}}'

You want to be careful when crafting the JSON of your notification. The server is pretty good about noticing mistakes, but on more than one occasion I screwed that part up. Note that you include the state information in the payload section. Also note that I didn't bother sending state params either.

So... this worked! And it was cool! Then I tested again and it failed. Sad kitty. Why? Did you notice the preference back there in register was canRunActionsOnWake? Specifically - "OnWake". So this feature only works automatically if the application is woken up - not if it is active.

If you think about it, that makes sense. As a user, I don't want the app automatically shifting focus when a notification comes in. However, you may be curious as to how you could possibly handle this. I modified my notification handler to add in some new logic - just for this:

onNotification: function(notification) {
      // Handle new push notifications here
      console.log(notification);
      if(notification["$state"]) {
        //prompt the user to switch
        navigator.notification.confirm("You have a new chat - go to it?", function(btn) {
          if(btn === 1) {
            $state.go(notification["$state"]);
          }
        },"New Chat!")
      }
      return true;
}

The modification is simple. I had added the Dialogs plugin and then made use of it in my handler. If I see a $state parameter I simply ask the user if they want to view the chats. If they say yes, I switch to it.

Now - to be clear - my logic could be a bit tighter. I don't actually look at the $state value. I should see if it exists and if is tabs.chat, but you get the idea. Here it is in action:

shot1

You can grab the full source code here: https://github.com/cfjedimaster/Cordova-Examples/tree/master/push2.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 (In reply to #0) by Raymond Camden posted on 9/1/2015 at 2:33 PM

In my case I'm not, so it uses a default value. If you look at this doc, http://docs.ionic.io/docs/p..., they have a better demonstration of working with the User stuff. My post was from an earlier version.

Comment 2 by ifelere Oyetola posted on 9/22/2015 at 11:04 AM

This has been so important to me! Thanks for sharing it.

Comment 3 by Hugh Hou posted on 10/1/2015 at 1:37 AM

I still can not get this to work by following your example...I have stateParam in my state tho. I wrote a stackoverflow question here: http://stackoverflow.com/qu...

Comment 4 (In reply to #3) by Raymond Camden posted on 10/2/2015 at 1:31 AM

It looks like you got it working.

Comment 5 by Luke Hartman posted on 1/18/2016 at 11:33 PM

Raymond,

Thanks for this post. I got the code to work in my app but was wondering if the app can handle push notifications without user interaction. My device is receiving push notifications and will open to a state passed in the payload, but I'd like the handler to trigger whether the user interacts with the notification or not (specifically saving the notification object to localstorage and incrementing the badge number).

Comment 6 (In reply to #5) by Raymond Camden posted on 1/19/2016 at 11:56 AM

Hmm. So basically - I get a notification. I do NOT click on it. I open the app. The app acts as if I did.

As a user, I wouldn't like that normally. ;)

But no - I don't think you have *automatic* support for that, but you could build this manually.

So imagine the notification is "New Email". If you have a REST API that returns true/false based on that, you can call that on startup and then respond accordingly.

Comment 7 (In reply to #6) by Luke Hartman posted on 1/19/2016 at 1:07 PM

Gotcha. That makes sense. Thanks for the suggestion.

Comment 8 by Bjørn Broer posted on 6/23/2016 at 2:13 PM

I want to thank you very, very much for this guide! I have been searching the official Ionic documents to lighten up this conundrum, so far unsuccessful. Thanks to you, I understood how to add custom payload, including how to use this to navigate the user to a certain page.

Thanks a thousand times!

Comment 9 (In reply to #8) by Raymond Camden posted on 6/23/2016 at 2:32 PM

You are most welcome. As a warning, the Ionic Services platform has changed quite a bit since I published this, so I don't want to promise it will work as is. Use with caution!

Comment 10 (In reply to #9) by Bjørn Broer posted on 6/23/2016 at 2:55 PM

It still works the way you wrote it. It will probably change in the upcoming update though, when Ionic goes out of it's Alpha/Beta stage.

Comment 11 by akash kabra posted on 7/17/2016 at 10:53 PM

Hello thanks for your tutorial ...!! Can you help in regarding action button in ionic push notification

Comment 12 (In reply to #11) by Raymond Camden posted on 7/18/2016 at 12:12 PM

Do you mean in the notification UI?

Comment 13 (In reply to #12) by akash kabra posted on 7/18/2016 at 8:14 PM

https://github.com/phonegap...

Please see above your , where they have gave the example.

But i am confused where should i add "actions" in my notification variable and how to send it to the ionic push server.

Comment 14 (In reply to #13) by Raymond Camden posted on 7/18/2016 at 8:41 PM

It would be done via the REST call to the Ionic server. Look in here: http://docs.ionic.io/docs/p...

Comment 15 (In reply to #14) by akash kabra posted on 7/18/2016 at 8:49 PM

Thanks. as the tutorial says

{
"notification": {
"title": "Hi",
"message": "Hello world!",
"android": {
"data": {
"image": // url
}
}
}
}

So should i replace the "data" tag with "Actions":

Please let me know if i am correct.

IF you can send me one of the example with action tag it will be great

Comment 16 (In reply to #15) by Raymond Camden posted on 7/18/2016 at 9:14 PM

I think it goes "under" data. You should check the docs of the Push plugin as I think it is documented there, not at Ionic. Worse comes to worse, ask on the Ionic forums.

Yes - I'm punting now. ;)

Comment 17 (In reply to #16) by akash kabra posted on 7/18/2016 at 9:20 PM

yes i gone through documentation.
I will try and let you know what is the outcome.
and while going through few links i saw many post regarding the "callback:" tag in actions facing issue .

Thanks for helping .. :)

Comment 18 by Jack posted on 12/15/2016 at 10:07 AM

So here you have used CURL , how to do this same thing with FIREBASE Cloud Messaging .

Comment 19 (In reply to #18) by Raymond Camden posted on 12/15/2016 at 12:55 PM

I used Curl to fire off an API request to create a push - but I was using Ionic's Push service to actually *do* the Push. Firebase Cloud Messaging would be another service. How you use it would be in their own docs, and you could use that instead of Ionic's of course.

Comment 20 by valmy roi posted on 4/5/2017 at 2:55 PM

How can i increase the badge number without forcing the user to click on the notification?

Comment 21 (In reply to #20) by Raymond Camden posted on 4/5/2017 at 3:47 PM

Are you saying that's required? I didn't think it was.

Comment 22 (In reply to #21) by valmy roi posted on 4/5/2017 at 3:54 PM

Actually in my project i'm using ionic.io for push notifictions and cordova badge plugin. What i want to do is to increse the icon badge number as the notification arrives on the phone (ios and android). Unfurtunately, all what i'm capable to do now is to increase the badge number when the user clicks on the notification message cause i don't know if there is an event or something like that to manage when the notification arrives. Thank you

Comment 23 (In reply to #22) by Raymond Camden posted on 4/5/2017 at 3:57 PM

That I'm not sure of - sorry.