Send push notifications to apple devices using PhoneGap and Java (iOS Push Notifications Part-III)

Anjana Pai Rathod
8 min readApr 25, 2016

Recently I was asked to configure push notifications for a hybrid mobile app I was working on. Looking at the popularity of push notifications I did not expect it to be that difficult, but in reality it did take me a lot of time to research and configure push notifications for iOS devices (I did the same thing for android devices too, however working on android was faster and simpler partially because I have an android background and knew my way though google libraries). The fact that it was my first time working on a mac further added to the confusion. Not having used a mac book ever costed me a lot of time and to add to it I had no idea what apple certificates were and how they work.

In an attempt to help apple newbies and developers trying to configure push notifications for their mobile apps, I have noted down all the step by step procedure if you want your iOS apps to send push notifications to your users.

Before jumping into specifics, I would suggest going though the anatomy of apple push notifications published here. This page will give you all the conceptual details you would need to know about apple push notifications.

For a background, I am developing a simple demo app using PhoneGap to handle my push notifications — this demo app would be my client which receives push notification from a server.

Usually people go for a third party server like Urban Airship to send push notifications to their clients(registered mobile devices) however since my company had their own servers I had to write a code to send push notifications from the in-house servers. Since rest of the back end code was written in java — that was the obvious choice of language for server side code. PHP is also a preferred language for the server side code, however I decided to stick to Java.

Also note that I haven’t used Xcode at any point since I wanted to make an hybrid app so the use of Xcode wasn’t necessary.

You can use PhoneGap and Cordova interchangeably since they have very minimal differences. However I have tried to stick to PhoneGap in all my commands/instructions below for the sake of consistency.

I will take you through each and every step of installation and code and by the end of this tutorial you should have a successful notification sent to you apple device from a local server running on your system.

Pre-requisites :

  1. iOS device (would need a real phone since push notifications don’t work on simulators).
  2. Mac OS running computer.
  3. Paid apple membership account. Without that you will not be able to generate the necessary certificates.

The following two blogs will help you get your apple certificates right and understand the build deploy process on Adobe PhoneGap build.

Creating apple signing certificates.

Using Adobe PhoneGap Build.

If you have followed the above two blogs, you should have all your certificates ready and a Hello World app deployed to your iPhone.

Now you are all set to dive into the client and server code.

Client Side Configuration for Push Notifications:

  1. Open Terminal app on your mac and navigate to the Hello World app directory.

2. If you notice when you add the iOS platform to your newly created PhoneGap app, some plugins are automatically added to your project. You can check the config.xml file or the terminal output to see which plugins are added. Also in your project directory under the plugins folder you can see all the plugins that were added.

Terminal output while adding iOS platform to phonegap application.
Plugins added while adding iOS platform

But we need to manually add the PhoneGap Push Plugin to the app using the CLI.

To install the plugin, go to your project directory and fire the following command

phonegap plugin add phonegap-plugin-push --variable SENDER_ID="Not Required for iOS"

We do not use the sender_id for iOS so you can put any value in here.

This should install the plugin to your project. Verify the terminal output and push plugin folder in your plugins folder as given below :

Push Plugin installed.

3. You will also need to add the plugin in config.xml. Insert the following line in your config.xml file :

<plugin name=”phonegap-plugin-push” spec=”~1.5.3" />
Manually add this line in config.xml

4. Next add the following lines of code to your index.html

<body>
<div class=”app”>
<h1>iOS Push Notifications</h1>
<p id= “RegText”>Registration ID : </p>
<p id=”regId”></p><br>
</div>
<div id=”cards” class = “message”>
</div>
<script type=”text/javascript” src=”cordova.js”></script>
<script type=”text/javascript” src=”js/index.js”></script>
<script type=”text/javascript”>
app.initialize();
</script>
</body>

5. Also add the following lines of code to your index.js inside onDeviceReady() function :

document.getElementById(‘regId’).innerHTML = ‘true’;
app.push = PushNotification.init({
“android”: {},
“ios”: {
“sound”: true,
“vibration”: true,
“badge”: true
},
“windows”: {}
});
app.push.on(‘registration’, function(data) {
console.log(“registration event: “ + data.registrationId);
document.getElementById(“regId”).innerHTML = data.registrationId;
var oldRegId = localStorage.getItem(‘registrationId’);
if (oldRegId !== data.registrationId) {
// Save new registration ID
localStorage.setItem(‘registrationId’, data.registrationId);
// Post registrationId to your app server as the value has changed
}
});
app.push.on(‘error’, function(e) {
console.log(“push error = “ + e.message);
});

app.push.on(‘notification’, function(data) {
console.log(‘notification event’);
var cards = document.getElementById(“cards”);
var push = ‘<p> Push Notification Text : </p>’
+’<p>’ + data.message + ‘</p>’;
cards.innerHTML += push;
});

In addition to these two files, I have just done some css changes in index.css so that my registration id and the push message are displayed in the right form.

You can find a working copy of this app in my GitHub repository.

Replace your www folder with the www folder in the above repository and you will get all the modifications you need.

There are two things your client app would do once you make the above changes :

a. Communicate with APNS and get a registration id — this is necessary to identify the device to which the push message needs to be sent to.

b. Display the push message text onto your app screen.

6. build and deploy your app to check if your device is registering with apple and getting back a registration id:

You should see something like this on your phone :

You should get this screen once you install and run the app. Click OK to accept.
The app registers the device with APNS and gets back a registration ID.

Your client app is all set and we can go over to the server side.

Server Side Configuration for Push Notifications:

At this point you have an iOS app which has registered for push notifications and APNS has returned back a registration id.

Follow the steps below to write a java code to which will send push notifications to this device :

  1. Retrieve the registration id

We would need to copy the registration id in the server side code. The easiest way of copying the registration id is through safari inspect.

a. Connect your phone to your mac.

b. Run the app on the phone.

c. Start-up safari → develop → <your iPhone> → index.html.

d. Your registration id will be listed in the index file.

Copy registration id from here and paste into your java code as shown in next step.

2. In your preferred java editor create a java project and copy the following code in a java class file:

package iOSPushNotifications;import com.notnoop.apns.APNS;
import com.notnoop.apns.ApnsService;
import java.util.*;
public class SendNotifications
{
ApnsService pushService = APNS.newService()
.withCert(“<path to your server p12>”, “password to you server p12”)
.withSandboxDestination()
.build();

void notify(String message)
{
String payload = APNS.newPayload().alertBody(message).build();
String token = “<registration id>”;
pushService.push(token, payload);
Map<String, Date> inactiveDevices = pushService.getInactiveDevices();
for (String deviceToken : inactiveDevices.keySet())
{
Date inactiveAsOf = inactiveDevices.get(deviceToken);
System.out.println(“Inactive device token : “ +deviceToken);
System.out.println(“Tried to send notification at : “ +inactiveAsOf);
}

}
public static void main(String[] args)
{
try
{
SendNotifications object = new SendNotifications();
object.notify(“Notify my iPhone”);
}
catch(Exception e)
{
System.out.println(“Exception occured : “ +e.getMessage());
}
}
}

Here the inputs you would give is :

a. Path to your server p12 certificate → refer this link in case you do not have your server certificate.

b. Password for your server p12 → this should be the same password you used while exporting the certificate on Keychain Access application

c. Registration id of the device you want to send a notification to. This is the id we got in step 1 above.

Note that I am using the library com.notnoop.apns to establish a connection with APNS.

You can find more details on notnoop on this GitHub location.

That’s it, you are all set to send your push notifications.

Run the java application and you should see the notification pop-up on your device :

If you tap on the notification it will take you to your app where the message text will be displayed.

You can find this java application code at my GitHub repository.

Note that I have tried to keep the mobile app and the server code as basic as possible so that I can focus on just this functionality. In a real life scenario you would want to customize the push notification to meet your requirements.

Troubleshooting :

Following are the basic level check-points you should run through if you are stuck somewhere.

  1. Make sure that the mobile client app is still installed on your device when you run the java application.
  2. Make sure that your certificate password is correct.
  3. Make sure your certificate is in .p12 format.
  4. Make sure your certificate path is correct.
  5. Make sure that the registration id is valid and you are providing the same id in the server code as you can see on your mobile app. The registration id becomes invalid if you uninstalled the app. Every time you uninstall and install the app back, APNS provides a next registration id.
  6. The ports required by APNS may be blocked by your company firewall, make sure that you are able to make a connection with APNS.

To check if you are able to connect with APNS, you can run the following commands on telnet :

telnet gateway.sandbox.push.apple.com 2195

and

telnet gateway.push.apple.com 2195

In case you have any other issues apart from these, drop me a comment and I will be happy to help. You can also email me on anjana.pai.rathod@gmail.com if you want me to write on any technical topic related to mobile app development.

Have fun sending push notifications !!!

--

--