Ionic Push Notification - Android and iOS working

Hello all Ionites!

Push notifications are awesome. Everyone wants to implement them but implementing push notification in iOS or Android can be quite difficult without good tutorial. After asking so many forum/stackoverflow questions, I’m finally able to implement push notifications for both iOS and Android using APNS and FCM(earlier known as GCM) respectively.

To help others a little, I wrote down the full steps with screenshot and full code on Github. Below are all the useful links.

Github Ionic 2 code

Github Push Server code

@brandyshea @tim @adam To Ionic Team, I’m not promoting or earning anything from these links. Just posted because everyday people ask so many push notification question. Please let me know if this is not the right place.

[EDIT] - Code and links updated to use Ionic 2 RC0

Thanks

25 Likes

Thank you Ankush, I am busy following your tutorial.

I do have a few issues, please have a look if you have some time.

More details:

Thanks

Thanks @ankushagg93 , for providing decent material to follow in order to implement FCM and APNS in android/ios application.

As we are following your tutorial previously, now the updated article of push notification with FCM helps to lot of seekers.

Regards

@richardmarais [quote=“richardmarais, post:2, topic:64004”]
Question 2
is the YOUR_GCM_API_KEY the Server Key or Sender ID from FCM?
[/quote]

put there a Server Key generated by the FCM.

2 Likes

Does the plugin support PubSub?

Thank you Ankush ! It’s a very nice summary.

May I know could you share more about how to build the push server? We have server code now, but how can we trigger the notification from the push server? May I know is there any example?
(Sorry that I only have the knowledge of linux and PHP server)

Many thanks.

@ankushagg93
Yes, as @eheading said I’m also stuck at the push server part now. I’m not getting how to trigger the notification from the push server and how to perform with your code?
And also the AndroidPush.java not compiling anymore.

Thanks in advance.

@eheading @vaibsVB

https://github.com/aggarwalankush/push-notification-server/blob/master/src/main/java/AndroidPush.java

I just ran above code and it’s pushing notification to my device.
REMEMBER

  • Replace SERVER_KEY with your SERVER_KEY generated from FCM
  • Replace DEVICE_TOKEN with your DEVICE_TOKEN generated from device

Also for compilation,

  • Clone this repository.
  • Run mvn install from the project root.

@ankushagg93 I followed all steps provided by you on Github.
But I’m getting error while performing this command:

javac AndroidPush.java

this is error log:

AndroidPush.java:1: error: package org.json does not exist
import org.json.JSONObject;
^
AndroidPush.java:20: error: cannot find symbol
JSONObject jFcmData = new JSONObject();

That’s because you didn’t do mvn install which will install org.json for you. If you see, getting started part in instructions https://github.com/aggarwalankush/push-notification-server, it’s mentioned.

@ankushagg93 I performed mvn install command prior to that.

The some of the output of above command I’m pasting here.

$ mvn install
[INFO] Scanning for projects…
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building push-notification-server 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] — maven-resources-plugin:2.3:resources (default-resources) @ push-notification-server —
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /home/bista/Downloads/push-notification-server-master/src/main/resources
[INFO]
[INFO] — maven-compiler-plugin:2.0.2:compile (default-compile) @ push-notification-server —
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] — maven-resources-plugin:2.3:testResources (default-testResources) @ push-notification-server —
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /home/bista/Downloads/push-notification-server-master/src/test/resources
[INFO]
[INFO] — maven-compiler-plugin:2.0.2:testCompile (default-testCompile) @ push-notification-server —
[INFO] No sources to compile
[INFO]
[INFO] — maven-surefire-plugin:2.10:test (default-test) @ push-notification-server —
[INFO] No tests to run.
[INFO] Surefire report directory: /home/bista/Downloads/push-notification-server-master/target/surefire-reports


T E S T S

Results :

Tests run: 0, Failures: 0, Errors: 0, Skipped: 0

[INFO]
[INFO] — maven-jar-plugin:2.2:jar (default-jar) @ push-notification-server —
[INFO]
[INFO] — maven-install-plugin:2.3:install (default-install) @ push-notification-server —
[INFO] Installing /home/bista/Downloads/push-notification-server-master/target/push-notification-server-1.0-SNAPSHOT.jar to /home/bista/.m2/repository/com/aggarwalankush/push-notification-server/1.0-SNAPSHOT/push-notification-server-1.0-SNAPSHOT.jar
[INFO] Installing /home/bista/Downloads/push-notification-server-master/pom.xml to /home/bista/.m2/repository/com/aggarwalankush/push-notification-server/1.0-SNAPSHOT/push-notification-server-1.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.153s
[INFO] Finished at: Wed Sep 21 20:21:55 IST 2016
[INFO] Final Memory: 8M/147M
[INFO] ------------------------------------------------------------------------

What happens if you want to push a notification to a device other than your own?

In my production app, push.on(‘registration’) function send device token along with username to my server. So I know device token of all users and I can push notification to any user.

 push.on('registration', (data) => {
                console.log("device token ->", data.registrationId);
                //TODO - send device token to server      <-- I implemented this part
 });

I think if you want to publish to an individual subscriber, you need to use topics.

   let topics: string[] = [id];

    let push = Push.init({
      android: {
        senderID: "xxxxxxxx",
        topics: topics
      },
      ios: {
        alert: "true",
        badge: false,
        sound: "true",
        topics: topics
      },
      windows: {}
    });

and then send a notification:

push.on('registration', (data) => {
  let promise: Promise<string> = this.notificationService.push(data.registrationId, 'This is a test message from Ionic Chat');
  promise.then((data) => {

  });
});

I have just tested this, and it doesn’t work. I think the problem may be that even though another user is subscribed to the topic I publish to, it is still only publishing to the data.registrationId (Device Token).

Does anyone know how to make it send to all subscribers on that topic?

This documentation says:

android.topics array [] Optional. If the array contains one or more strings each string will be used to subscribe to a GcmPubSub topic.

I think the following line, on the Java Server may be the problem, that is restricting it to only send notifications to the same device:

jGcmData.put("to", device_token);

However, if I remove this line, it still doesn’t work.

I see that, I always import project in IDE as Maven Project and run from IDE.

I updated the github to remove the dependency, you can now directly do

$ javac AndroidPush.java
$ java AndroidPush

REMEMBER

  • Replace SERVER_KEY with your SERVER_KEY generated from FCM
  • Replace DEVICE_TOKEN with your DEVICE_TOKEN generated from device
1 Like

@ankushagg93 Thanks. Now push notification working properly.

This in my view is fundamentally wrong. It only works on one device, because you push to a device_token. It should be pushed to all devices that subscribe to the message.

see:

"to": "/topics/foo-bar",

But how should this be formatted for multiple topics? (that’s just one topic foo-bar)

Need to Change the Java Server to send to the topic instead of the device:

jGcmData.put(“to”, “/topics/”+topics);

See this for more details:

Hi,

I updated to your new version of your tutorial. I see you have updated it to use: "https://fcm.googleapis.com/fcm/send". Thank you.

I have implemented exactly as your instructions say as far as I know.

Installed the plugin:

ionic plugin add https://github.com/phonegap/phonegap-plugin-push --variable SENDER_ID=”XXXXXXXXXXX”

package.json

"cordovaPlugins": [
    "cordova-plugin-device",
    "cordova-plugin-console",
    "cordova-plugin-whitelist",
    "cordova-plugin-splashscreen",
    "cordova-plugin-statusbar",
    "ionic-plugin-keyboard",
    {
      "variables": {
        "SENDER_ID": "XXXXXXXXXXX"
      },
      "locator": "phonegap-plugin-push",
      "id": "phonegap-plugin-push"
    }
  ],
  "cordovaPlatforms": []

registration

  let push = Push.init({
    android: {
      senderID: "XXXXXXXXXXX"
    },
    ios: {
      alert: "true",
      badge: false,
      sound: "true"
    },
    windows: {}
  });

  push.on('registration', (data) => {
    let promise: Promise<string> = this.notificationService.push(data.registrationId, topics[0], message, this.activeChat.title); // <== calls the Java server
    promise.then((data) => {
      alert('push: data = ' + data);
      //return;
    });
  });

I get the Java Server to push the message:

{"data":{"title":"title","message":"Test"},"to":"dvpiJM32QwE:APA91bECzkuTUHYtpZN3OFrq6xOWep_twj3mN1TcI0F0DaKY92Rp8gwHz2Z-U1HI1_EA_Jp0Hu2zGBw1sKhxqrZUlmTUWnXHG8v0J66HXm7Nw9yPSKep9b_TGQ0SNT8cDEmFoZgpu5lo"}

[stdout] (default task-6) 200
[stdout] (default task-6) OK

However, my Android App is not receiving it.

notification

app.ts

        let push = Push.init({
            android: {
                senderID: "XXXXXXXXXXX"
            },
            ios: {
                alert: "true",
                badge: false,
                sound: "true"
            },
            windows: {}
        });

        push.on('notification', (data) => {
            alert('Received Notification!!! message = '+data.message);
        });
        push.on('error', (e) => {
          alert('Error: '+e.message);
            console.log(e.message);
        });

The alert('Received Notification!!! message = '+data.message); is not being triggered and my device does not receive a notification.

Do you know what I am doing incorrectly?

Thanks

I think you need to use AlertController to present/show the alert. As we do in IONIC-2 to show alert.
The normal alert(); may not work in this typescript code.
Let’s have a try.

1 Like

Thanks,

Normal alert() does seem to work for me. I have tried it with the AlertController with no success too. I just use alert() to try debug it. I think my issue is the notification listener is not being called, as there is no notification.

I will however try another time with the AlertController.

You may want to look here how I’m showing alert https://github.com/aggarwalankush/ionic2-push-base/blob/master/app/app.ts

                let confirmAlert = Alert.create({
                    title: 'New Notification',
                    message: data.message,
                    buttons: [{
                        text: 'Ignore',
                        role: 'cancel'
                    }, {
                        text: 'View',
                        handler: () => {
                            //TODO: Your logic here
                            self.nav.push(DetailsPage, {message:data.message});
                        }
                    }]
                });
                self.nav.present(confirmAlert);

currently it’s based on Ionic 2 beta 10. If you are using beta 11, use AlertController which is just one word change. for details, see https://github.com/driftyco/ionic/blob/master/CHANGELOG.md

I’ll update once Ionic 2 beta 12 is released.

1 Like