Implementing Push Notifications with Ionic

January 6, 2017, 3:29 pm Categories:

Categories

Push Notifications

** UPDATED FOR IONIC 3 **

If you've used your smartphone for any length of time you'll be familiar with push notifications - small messages that pop up on the screen, whether you happen to be using a certain app or not and even when the device is 'asleep'.

These are a handy way to keep user's engaged with your app while also providing relevant news and informational updates where necessary.

In the following tutorial I'm going to take you through integrating OneSignal's free push notification service with Ionic using the OneSignal Apache Cordova/Ionic Native plugin.

This will involve a number of steps along the way:

  • Creating an account/application with OneSignal
  • Generating iOS signing certificates
  • Creating iOS provisioning profiles
  • Configuring iOS & Android SDK's for OneSignal
  • Implementing plugin API methods
  • Creating, sending & testing our first push notification

There's a lot to get through but I'll break all of the above down section-by-section so don't worry if it might seem a little overwhelming at first, you'll soon become an expert with the different requirements and processes involved!

Requirements & expectations

FYI: This tutorial is based on a Mac OS X development environment using the following software and devices:

  • Ionic 3.0.1
  • Apache Cordova 6.5.0
  • Mac OS X Sierra v10.12.4
  • Xcode 8.3.1
  • Android SDK Tools 25.2.2
  • Android SDK Platform Tools 25
  • Android 7.1.1 (API 25)
  • Android Galaxy S4 Mini (Android 4.4.2)
  • IPhone 5C (iOS 9.3.2)

I know from personal experience that this tutorial will work on the above environment(s) but I cannot guarantee that this will be the case with your own environment. As always in these situations use your best judgement and common sense with moving forwards!

By the end of the tutorial you should have a very basic Ionic application that is able to receive and display push notifications as shown in the following screen captures:

Now you have an idea of what to expect let's start by familiarising ourselves with OneSignal.

Push notifications ala OneSignal

OneSignal provides free push notification services supported across a variety of platforms with multiple SDK's for developers to choose from. Given the service is free it's pretty much a non-brainer as far as cost goes (not to mention feature support) but, as the saying goes, there is no such thing as a free lunch.

Caveat Emptor: OneSignal makes money from sharing with its clients the data supplied by users of its service. IF you are concerned about privacy (and in this digital age of inter-connectedness where an individual's personal details are almost always available at the click of a button you SHOULD be concerned with privacy) then you need to read OneSignal's Terms of Use and Privacy Policy to be sure you're comfortable with what's being shared and monetised from the data you provide when using the service.

Assuming that you're comfortable with using OneSignal's service the first thing you'll need to do is create an account (scroll down towards the bottom of the page and click on the SIGN UP FREE button).

Once an account with OneSignal has been created you can start implementing the service in iOS & Android but only after you've generated the following:

  • iOS signing certificates
  • Firebase Console Messaging project credentials
  • Installed and configured the required SDK (or, in the case of this tutorial, the required Ionic Native/Apache Cordova plugin)

Let's start with iOS as configuring this platform with the necessary certificates for OneSignal is - to say the least - a little more involved than the steps required for Android (this is thanks to Apple's famous walled garden policy which, in my humble opinion, subsequently makes for a more secure app experience....even if configuring the required certificates and profiles can be tedious and frustrating to work through!)

Integrating OneSignal with iOS for your mobile app requires the following elements:

  • Explicit App ID
  • Signing certificate
  • .p12 certificate
  • App distribution profile

Let's work through each of these steps starting with creating a signing certificate request file.

Codesigning with iOS #1 - Creating a signing certificate request file

A signing certificate request file provides encrypted information to digital certificates that are used to code sign iOS mobile apps. Without these certificates we won't be able to generate provisioning profiles for development and distribution of our apps so it's safe to say this is a pretty important step we need to complete!

Open the Keychain Access utility on your Mac (situated in your Applications/Utilities directory) and from the Keychain Access menu select Certificate Assistant and then Request a Certificate From a Certificate Authority:

Requesting a Certificate Authority in Mac OS X Keychain Access software

Following from this a Certificate Assistant wizard will guide you through creating the certificate request file.

You will need to enter/select the following:

  • User Email Address
  • Common Name
  • Saved to disk

Entering certificate information in Mac OS X Keychain Access software

Ensure you save the CertificateSigningRequest.certSigningRequest file to an easily accessible location on your computer (I.e. the Desktop):

Saving generated certificate request file to desktop in Mac OS X

With the signing certificate request file successfully created we can now move onto creating an explicit App ID.

Codesigning with iOS #2 - Creating an explicit App ID

In order to use specific services within your iOS app such as In-app Purchases or - in the case of this tutorial - push notifications, you will need to register an explicit App ID (which is a unique identifier specific to a single iOS app).

Log into your Apple Developer account, navigate to Certificates, Identifiers & Profiles and create a new App ID as shown below:

Registering an App ID in the online Apple Developer account

Here I've entered a descriptive name of Pusha and a Bundle ID of com.saintsatplay.pusha (which will be used in the config.xml file of the Ionic app we'll be creating a little later on in this tutorial).

You can enter whatever Bundle ID you want for your App ID but it's best to stick to a reverse domain name convention (I.e. com.saintsatplay.pusha).

Within the App Services section ensure that the Push Notifications checkbox has been selected:

Selecting services when registering an App ID in the online Apple Developer account

Continue to the next screen where your App ID should be now created.

We'll use this App ID in the next step to configure the necessary production certificate for our Push Notifications (so as to authorise the app to be able to communicate with the Apple Push Notification Service).

Codesigning with iOS #3 - Creating a.p12 certificate

From the Certificates, Identifiers & Profiles section, within your Apple Developer account, create a new Certificate from the following option:

  • Production > Apple Push Notification service SSL (Sandbox & Production)

This will allow us to generate a Production ready certificate that works across both Sandbox & Production environments (which is useful as we won't need to generate separate certificates for each environment):

Creating a Production push certificate

On the following screen you'll then be prompted to create a Certificate Signing Request (CSR) file:

Creating a Certificate Signing Request (CSR) file

Upload the CSR file that was created in the Codesigning with iOS #1 section:

Uploaded Certificate Signing Request (CSR) file

Proceed to the next screen where your generated certificate should be available for download:

Generated push certificate available for download

Download the certificate to your computer and then double click on this file to open it within your Keychain Access utility:

Downloaded push certificate selected in Keychain Access utility

Right click on the selected certificate and select Export from the contextual menu options:

Exporting selected push certificate in Keychain Access utility

The selected certificate will then be exported as a .p12 certificate (which is a format required when configuring the iOS platform through OneSignal).

At this stage ensure that you enter a recognisable name for the exported certificate and select a suitable location on your computer where the file will be saved to:

Exporting to a p12 certificate in Keychain Access utility

Enter a password for the generated p12 file (and be sure to make a note of this as you will need this password when configuring your iOS app in OneSignal).

You'll be prompted for your system password to save these changes and, once done, you should have a generated .p12 certificate saved to your computer.

Now one last step remains with our iOS codesigning set-up - creating a distribution profile so that we can test our app on a real world iOS device.

Codesigning with iOS #4 - Generating an app distribution profile

Returning to your Apple Developer account create an Ad Hoc distribution profile:

Selecting an ad-hoc distribution provisioning profile

As you progress through the different configuration screens you'll need to:

  • Select the Pusha specific App ID that was created earlier
  • Select the device(s) that the certificate will be applied to
  • Provide a memorable name for the certificate (so as to easily identify this in the provisioning portal)

By the end of the configuration process you should possess a distribution certificate with credentials akin to the following:

Completed ad-hoc distribution provisioning profile ready for download

Later on we'll import this distribution certificate into Xcode when we start developing the Ionic app.

At this point I would also create a development provisioning profile for use with your app (which will essentially be a repeat of the above process except you will opt, from the outset, for selecting development over distribution).

For now though that concludes our iOS codesigning set-up (until we return to working with Xcode) so let's turn our attention to configuring Android.

Codesigning with Android

Thankfully Android is a much simpler platform to configure push notifications for use with OneSignal. All we need to do here is generate a server key and project ID - both of which we'll obtain courtesy of Firebase.

If you don't already have an account with Firebase create one (it's free).

If you do then great, simply log in and select an existing project (or create a new one).

Navigate to your project Settings page, select the CLOUD MESSAGING menu option and copy both the Server Key and Sender ID values that are displayed there. Both of these will be used in the OneSignal set up of your Android App and the Sender ID value will be required when integrating the OneSignal Ionic Native plugin into our forthcoming Ionic app - so be sure to store both of these values somewhere safe!

Firebase project settings screen

And, believe it or not, that concludes the codesigning set-up for Android.

Told you it was simple didn't I?

Now that we have the necessary certificates and server keys for iOS & Android let's set up both of these platforms in OneSignal.

OneSignal - Setting up iOS

Once your account with OneSignal has been created you can begin adding applications (which will correspond to their mobile/web application counterparts) like so:

Adding a new application in OneSignal

Here I've named the app I'm creating for this tutorial as Pusha (we'll subsequently create an Ionic application of the same name).

Once our new OneSignal app has been created we'll be prompted to select a platform to associate the app with:

Select a platform for a new application in OneSignal

In the above I've selected iOS as the platform to configure for this application. We can always return to the App Settings screen of our OneSignal account and add further platforms later on (which we will be doing with Google Android).

On the following screen we'll configure the selected iOS platform.

In order to ensure that our iOS application can communicate with OneSignal to facilitate push notification we need to upload the .p12 production certificate that we previously generated in the section titled Codesigning with iOS #3 - Creating a.p12 certificate.

We also need to enter the password that we used to save the .p12 certificate (NOT your system password):

Adding a .p12 certificate and password for the iOS platform with OneSignal

Save this selection and proceed to the next screen where you will be invited to select a specific mobile development SDK.

Important: even though you will be installing an Ionic Native plugin to implement the push notification service you still need to obtain the OneSignal Application ID (which can only be accomplished by selecting an SDK and proceeding to the end of the App set-up wizard.)

From the available options select Phonegap, Cordova, Ionic, Intel XDK:

Selecting the Phonegap, Cordova, Ionic and Intel XDK SDK option for the iOS platform with OneSignal

On the final screen of the app set-up wizard select the App ID value (displayed in the blurred out section of the screen capture below) and store this somewhere safe. You will be using this when configuring the OneSignal Ionic Native plugin:

Selecting the OneSignal App ID for the iOS platform

With the configuration for our iOS platform concluded all that remains is to do the same with Android.

OneSignal - Setting up Android

Navigate to your App Dashboard and select the App Settings menu link from the left hand sidebar:

OneSignal Push App dashboard

Scroll down the list of displayed Platforms, stop where Google Android is displayed and click on the Configure button:

OneSignal Push App configure Native platforms

Thankfully there's only one configuration screen to work with for Android!

In the Google Server API Key input field paste the Server Key value you copied from your Firebase project.

In the Google Project Number input field paste the Sender ID value you copied from your Firebase project.

OneSignal Push App configure Android platform

Save this and that's all the configuration requirements completed for Android.

With both iOS & Android configured for OneSignal we can now turn our attention to creating an Ionic application and implementing the OneSignal push notification service within there.

Creating the Pusha Ionic app

Using your system CLI (I.e. Terminal on Mac OS X or the Command Prompt on Windows) navigate to the root of your projects directory (or wherever you would normally create your mobile applications) and issue the following command:

ionic start pusha blank

Once the software has completed being installed to your system run the following CLI commands:

cd pusha
ionic cordova plugin add onesignal-cordova-plugin
npm install --save @ionic-native/onesignal

Here we're simply installing the OneSignal Ionic Native plugin.

In the pusha/src/pages/home/home.ts file we implement the code for communicating with the OneSignal service as follows:

import { Component } from '@angular/core';
import { NavController, Platform } from 'ionic-angular';
import { OneSignal } from '@ionic-native/onesignal';


@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

   constructor(public navCtrl    : NavController,
               private _PLATFORM : Platform,
               private _SIGNAL   : OneSignal) 
   {
      this._PLATFORM.ready()
      .then(() =>
      {
         this.triggerNotification();
      });
   }



   triggerNotification()
   {

      // Define settings for iOS
      var iosSettings = {};
      iosSettings["kOSSettingsKeyAutoPrompt"] = true;
      iosSettings["kOSSettingsKeyInAppLaunchURL"] = false; 


      // Initialise plugin with OneSignal service
      this._SIGNAL.startInit(One-Signal-Application-ID-Pasted-Here, Firebase-Sender-ID-Pasted-Here).iOSSettings(iosSettings);


      // Control how OneSignal notifications will be shown when 
      // one is received while your app is in focus
      this._SIGNAL.inFocusDisplaying(OneSignal.OSInFocusDisplayOption.InAppAlert);


      // Retrieve the OneSignal user id and the device token
      this._SIGNAL.getIds()
      .then((ids) => 
      {
         console.log('getIds: ' + JSON.stringify(ids));
      });


      // When a push notification is received handle 
      // how the application will respond
      this._SIGNAL.handleNotificationReceived()
      .subscribe((msg) => 
      {
         // Log data received from the push notification service
         console.log('Notification received');
         console.dir(msg);
      });


      // When a push notification is opened by the user
      // handle how the application will respond
      this._SIGNAL.handleNotificationOpened()
      .subscribe((msg) => 
      {
         // Log data received from the push notification service
         console.log('Notification opened');
         console.dir(msg);
      });


      // End plugin initialisation
      this._SIGNAL.endInit();

   }

}

Even though the above code is fairly simple there are a few points worth elaborating on.

Other than declaring the modules to be imported we start, as we always do whenever a plugin is used within an Ionic application, by using the Platform component to ensure that the device is ready for any calls to the OneSignal plugin's API methods.

constructor(public navCtrl    : NavController,
            private _PLATFORM : Platform,
            private _SIGNAL   : OneSignal) 
{
   this._PLATFORM.ready()
   .then(() =>
   {
      this.triggerNotification();
   });
}

Here we simply run the triggerNotification method which contains all of the following OneSignal plugin API methods:

  • startInit
  • inFocusDisplaying
  • getIds
  • handleNotificationReceived
  • handleNotificationOpened

Each of these methods have been fully commented to provide information on their purpose and correct application:

triggerNotification()
{

   // Define settings for iOS
   var iosSettings = {};
   iosSettings["kOSSettingsKeyAutoPrompt"] = true;
   iosSettings["kOSSettingsKeyInAppLaunchURL"] = false; 


   // Initialise plugin with OneSignal service
   // 1st parameter = OneSignal Application ID
   // 2nd parameter = Firebase Sender ID (Android only - not needed if iOS only project)
   this._SIGNAL.startInit(One-Signal-Application-ID-Pasted-Here, 
                       Firebase-Sender-ID-Pasted-Here)
   .iOSSettings(iosSettings);


   // Control how OneSignal notifications will be shown when 
   // one is received while your app is in focus
   this._SIGNAL.inFocusDisplaying(OneSignal.OSInFocusDisplayOption.InAppAlert);


   // Retrieve the OneSignal user id and the device token
   this._SIGNAL.getIds()
   .then((ids) => 
   {
      console.log('getIds: ' + JSON.stringify(ids));
   });


   // When a push notification is received handle 
   // how the application will respond
   this._SIGNAL.handleNotificationReceived()
   .subscribe((msg) => 
   {
      // Log data received from the push notification service
      console.log('Notification received');
      console.dir(msg);
   });


   // When a push notification is opened by the user
   // handle how the application will respond
   this._SIGNAL.handleNotificationOpened()
   .subscribe((msg) => 
   {
      // Log data received from the push notification service
      console.log('Notification opened');
      console.dir(msg);
   });


   // End plugin initialisation
   this._SIGNAL.endInit();

}

I've simply logged data to the console with some of the above methods purely to demonstrate what's being returned from the OneSignal service but this could always be improved upon with more enhanced logic (if required).

I could have separated and packaged these methods into a provider but for the purposes of this tutorial all I'm interested in is demonstrating the push notification service working between the OneSignal service and the Pusha Ionic application.

I'll leave it to you to separate these out if you want to organise the code a little more cleanly.

Debugging

If you want to debug the integration between your Ionic application using the OneSignal Cordova plugin and the actual OneSignal service itself simply add the following towards the end of the triggerNotification method:

this._SIGNAL.setLogLevel({logLevel: 6, visualLevel: 6});

The values for the setLogLevel method can be adjusted from no debugging information being displayed to strongly verbose instead.

FYI: the above settings are VERY verbose!

Application HTML

The content for the pusha/src/pages/home/home.html file is fairly simple (consisting of a custom image I designed - feel free to add whatever content you want for this page):

<ion-header>
   <ion-navbar>
      <ion-title>
         Pusha
      </ion-title>
   </ion-navbar>
</ion-header>

<ion-content>

   <ion-item class="pusha">
      <img src="assets/images/pusha.png">
   </ion-item>

</ion-content>

This image is placed (as all custom images should be) in the src/assets directory in a custom directory that I've added to this location titled images.

When an ionic build process is run the images directory (along with all of its assets) is subsequently copied into the www/assets directory.

Styling

The following style rule has been added to the pusha/src/pages/home/home.scss file to ensure the image is displayed correctly:

page-home {   

   .pusha {
      width: 100%;
      height: 100%;
      padding: 0;
      background-color: rgb(205, 205, 205);

      img {
      	display: block;
      	margin: auto;
      }
   }

}

Nothing too drastic here just a simple aesthetic tweak!

Module management

In the application root module - pusha/src/app/app.module.ts - import and then declare the OneSignal module within the providers array like so:

import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { SplashScreen } from '@ionic-native/splash-screen';
import { StatusBar } from '@ionic-native/status-bar';
import { OneSignal } from '@ionic-native/onesignal';

import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';

@NgModule({
  declarations: [
    MyApp,
    HomePage
  ],
  imports: [
    BrowserModule,
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage
  ],
  providers: [
    StatusBar,
    SplashScreen,
    OneSignal,
    {provide: ErrorHandler, useClass: IonicErrorHandler}
  ]
})
export class AppModule {}

Icons & splash screens

The default cordova launch icons and splash screen images will look kind of lame when running the pusha app so you might want to update the following files with your own specific design:

  • pusha/resources/icon.png
  • pusha/resources/splash.png

Once you've done so, run the following command from the Ionic CLI at the root of your project:

ionic cordova resources

This will update the existing image files located in the resources directory for both iOS & Android.

Not only will this make your Ionic app look and feel a little more professional but when you build and run the application on iOS & Android devices any OneSignal push notifications will use the app launch icon for display.

Taking the time to customise the launch icons (and splash screen images) just helps polish the overall app experience so it's well worth the time investment.

Final steps

We're almost ready to start sending push notifications to the pusha application but there's a couple of additional tweaks that we need to make first.

In your pusha/config.xml file edit the widget id value to the following:

com.saintsatplay.pusha

// So you should end up with a line that looks like the following - broken for readability :)
<widget id="com.saintsatplay.pusha" 
        version="0.0.1" 
        xmlns="http://www.w3.org/ns/widgets"  
        xmlns:cdv="http://cordova.apache.org/ns/1.0">
 

If you're developing for iOS you'll need to perform the following steps in Xcode:

  • Enable Push Notifications
  • Enable Remote Notifications

Open the pusha.xcodeproj file, within Targets select pusha and then under Capabilities enable Push Notifications and Remote notifications as displayed below:

Configuring Push & Remote Notifications in Xcode

Finally ensure that under Xcode's pusha > Targets > Build Settings > Code Signing > Provisioning Profile settings that you've assigned the provisioning profiles created earlier:

 Xcode build settings

And with those final additions and amendments made we can now start testing our application before we send push notifications from OneSignal.

A word of warning...

When attempting to build a project using the OneSignal Ionic Native plugin you may encounter the following error:

Module 'node_modules/@ionic-native/core/index' has no exported member 'IonicNativePlugin'

IF this should happen then take a look at this article which details how to fix the issue.

Testing On iOS & Android

Deploying the application to your chosen platform is as simple as connecting a handheld device to your computer and running the following command from the Ionic CLI:

ionic cordova build android

// Once the build process has successfully completed run the following
ionic cordova run android

Substitute ios for android with the above commands if you're deploying to that platform instead (alternatively build with the ionic CLI and then run your application from Xcode).

You will need to run your pusha application once in order to register the app user as a subscribed user of the OneSignal service.

This can only happen when the user gives their permission to receive push notifications through the pusha Ionic app - as prompted through a permissions modal dialog (which is displayed the first time a user runs the app) as shown below:

 OneSignal permission modal

Sending push notifications

All things being well you now have a user registered with the OneSignal Pusha app - yourself!

This means that you can now start sending and receiving push notifications!

To do this log in to your OneSignal account, select your app and then, from the dashboard, under Common Actions select New push notification:

 OneSignal account dashboard

This will allow you to enter the necessary content for your push notification:

 OneSignal create push notification

Once created you can preview the push notification before publishing that to all subscribed users:

 OneSignal preview push notification

And, once published, you should see your push notifications being displayed on your iOS & Android devices like so:

 OneSignal push notifications displayed on iOS & Android

In summary

OneSignal makes push notifications a cinch with Ionic (thanks in addition to the Ionic Native/Apache Cordova plugin)...even with all the hoops we have to jump through to configure iOS and, to a much lesser extent, Android!

As long as you don't mind OneSignal's data aggregation and sharing (hey, even a free service comes with a cost right?) then this is definitely a must-have service/plugin integration for enabling push notifications with Ionic.

Feel free to use the above code in your own Ionic projects as you see fit and, if you're feeling generous, consider using the form below to leave a comment on this tutorial.

If you enjoyed what you've read here then please sign up to my mailing list and, if you haven't done so already, take a look at my e-book: Mastering Ionic for working with different aspects of the Ionic framework.

Tags

Categories

Post a comment

All comments are welcome and the rules are simple - be nice and do NOT engage in trolling, spamming, abusiveness or illegal behaviour. If you fail to observe these rules you will be permanently banned from being able to comment.

Top