I am implementing a Java Spring Framework server which sends an Apple Push Notification to an iPhone using Swift. Here are the things you will need:
1. Account setup
Assume you already have an Apple developer account with certificates, login https://developer.apple.com/ and go to the tab Identifiers and click “+” to add a new one. Fill in the prefix and suffix, then remember to check the box “Push Notifications”
Then select Edit, and scroll to the Push Notifications section, you will see the “Configurable” orange indicators. Create and download the Development SSL certificate using your CSR file. Double click to run and add to your key chain.
Open Keychain Access, find the certificate and export it as .p2 file. You will be prompt to enter a password, which better not to leave it blank. Otherwise, the Java Spring app may not be able to parse an empty string. Save this file, which will be used in later steps.
2. Xcode setup
Create a new Xcode project, such as a Single View Application. In the Capabilities tab, enable ‘Push Notifications’ with your Apple ID accounts login.
In the AppDelegate.swift, add a method to create an instance of settings, which get the user’s permission with a prompt when the app launches:
func registerForPushNotifications(application: UIApplication) {
let notificationSettings = UIUserNotificationSettings(
forTypes: [.Badge, .Sound, .Alert], categories: nil)
application.registerUserNotificationSettings(notificationSettings)
}
Invoke it when the finished launching:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
registerForPushNotifications(application)
return true
}
In the same AppDelegate.swift file, add the method below, which handles when a user accepts or declines the permissions.
func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
if notificationSettings.types != .None {
application.registerForRemoteNotifications()
}
}
Add the method below to handle if the registration is successful:
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
let tokenChars = UnsafePointer<CChar>(deviceToken.bytes)
var tokenString = “”
for i in 0..<deviceToken.length {
tokenString += String(format: “%02.2hhx”, arguments:[tokenChars[i]])
}
print(“Device Token:”, tokenString)
}
Also for failure case of the registration:
func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {
print(“Failed to register:”, error)
}
You can now try and run the app. Notice that you will need a physical device, instead of a simulator to test it out. If things go well, you should see the device token in the console. Record this for later use.
3. Java Spring Server setup
Create a Java spring framework server using your favourite IDE, like NetBeans or Intellij. In this example, we are using the maven build, with a pom.xml file like this:
<?xml version=”1.0" encoding=”UTF-8"?>
<project xmlns=”[http://maven.apache.org/POM/4.0.0](http://maven.apache.org/POM/4.0.0)" xmlns:xsi=”[http://www.w3.org/2001/XMLSchema-instance](http://www.w3.org/2001/XMLSchema-instance)"
xsi:schemaLocation=”[http://maven.apache.org/POM/4.0.0](http://maven.apache.org/POM/4.0.0) [http://maven.apache.org/xsd/maven-4.0.0.xsd](http://maven.apache.org/xsd/maven-4.0.0.xsd)">
<modelVersion>4.0.0</modelVersion>
<groupId>com.victorleungtw</groupId>
<artifactId>push-notification</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>push-notification</name>
<description>Push Notifcation</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.5.RELEASE</version>
<relativePath/> <! — lookup parent from repository →
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs-mockmvc</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Then we utilize the notnoop library from Maven Repository. Add this dependency to the pom.xml
<dependency>
<groupId>com.notnoop.apns</groupId>
<artifactId>apns</artifactId>
<version>1.0.0.Beta6</version>
</dependency>
When the server started, it would look for the main, with example PushNotificationApplication.java below:
package com.victorleungtw;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class PushNotificationApplication {
public static void main(String[] args) {
SpringApplication.run(PushNotificationApplication.class, args);
}
}
As a simple demo, we will create a NotificationController.java
package com.victorleungtw;
import java.util.Map;
import java.util.Date;
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.notnoop.apns.APNS;
import com.notnoop.apns.ApnsService;
/**
*
* @author victorleungtw
*/
@RestController
public class NotificationController {
private static final String template = “Hello, %s!”;
private final AtomicLong counter = new AtomicLong();
ApnsService service = null;
@RequestMapping(“/notification”)
public Notification notification(@RequestParam(value=”name”, defaultValue=”World”) String name) {
System.out.println(“Sending an iOS push notification…”);
ApnsService service = APNS.newService()
.withCert(“XXX.p12”, “YOUR_PASSWORD”)
.withSandboxDestination()
.build();
String payload = APNS.newPayload()
.alertBody(“Can’t be simpler than this!”)
.alertTitle(“test alert title”).build();
String token = “b8f3b2513caa.....”;
System.out.println(“payload: “+payload);
service.push(token, payload);
System.out.println(“The message has been hopefully sent…”);
return new Notification(counter.incrementAndGet(),
String.format(template, name));
}
}
Replace “XXX.p12”, “YOUR_PASSWORD” and “b8f3b2513caa…..” with your actual .p12 file path, password and the device token respectively. If you are not sure about the file path, you can put the .p12 file at the same level as your /src folder, i.e. the root of the project folder. That’s it. Run the following commands:
mvn install
And start the server:
mvn spring-boot:run
Open your browser, once you hit the route http://localhost:8080/notification, you should be able to receive a notification!
Let me know if you have any questions :)