Sending Push Notifications With Vapor
- Getting Started
- Understanding the Sample App’s Limitations
- Understanding and Configuring APNS
- APNS Device Registration Flow
- Creating the APNS Push Key
- Configuring the Server to Use the APNS Key
- Looking at the Device Model
- Using Push Channels
- Creating and Updating a Device With Routes
- Saving the Device Data From the iOS App
- Exposing the Local Server to the Web With Ngrok
- Running Ngrok
- Creating the First Device
- Updating the Device With the APNS Device Token
- Sending Push Notifications
- Targeting a Specific Device
- Sending a Notification to Channels
- Enriching the Notification
- Conforming to APNSwiftNotification
- Sending the Flight Notification to a Channel
- Testing the Flight Notification
- Where to Go From Here
Adding push notifications to your app enriches your users’ experience by delivering data to devices as it becomes available, rather than forcing users to constantly fetch that data.
If you want to add push notifications to your app, third party services like Firebase or OneSignal are easy to set up. In many cases, though, using the Apple Push Notification Service — APNS — directly from your server is a better option.
Using APNS means you don’t need to use a third party SDK in your iOS app. Plus, it means you don’t share your users’ data with any third-party companies.
In this tutorial, you’ll learn how to connect to APNS and how to send push notifications with Vapor. You’ll learn how to send notifications to a specific user’s device as well as to many devices via subscription channels.
You’ll do this by working on an app called AirplaneSpotter, which tells aviation enthusiasts when airplanes are about to land at the airports that interest them.
For this tutorial, you’ll need the following:
- An iOS device: Push notifications don’t work in a simulator, so you’ll need to use an actual device.
- An Apple Developer Program membership: To send push notifications, you need a push notification certificate for your app, which requires a program membership.
After opening the Starter folder in the downloaded materials, you’ll notice that there are three directories: one for the Server app, one for the iOS app and another for code shared between these two.
Open Package.swift in the Server folder, either by double-clicking it on Finder or by running
open Package.swift in Terminal. Xcode will open the Server app and start fetching all the required dependencies.
While Xcode is doing that, take the time to go over the existing code.
Start with the files in Sources/App/Models, which are: Airport.swift, Flight.swift and Device.swift.
In Migrations, you’ll see how to create each model and its associated properties in the database. You can add initial data in migrations as well, as shown in CreateAirport.swift.
Every model also has an associated controller, located in Controllers, which handles incoming requests.
After Xcode finishes resolving the project’s dependences, make sure you can run the project by selecting My Mac in the device pop-up and clicking the Run button — or by pressing Command-R.
Now, open the iOS starter project with Xcode and confirm that it compiles without any errors. Don’t run it yet, as the server isn’t ready, just press Command-B to build it. You can do this immediately, as it doesn’t have any external dependencies.
Understanding the Sample App’s Limitations
Before doing a quick recap of how APNS works, take a look at the limitations of this tutorial’s sample project:
- Scaling pushes: A single instance of a server running on Vapor can send notifications without delays to a few thousand devices. If you need to send notifications to hundreds of thousands — or millions — of users, it’s worth building a queuing system on top of Vapor.
Users: This tutorial has no concept of a user; every device is a separate row in the database. If your app has a User entity, you’ll want to link every user to a list of
Devices via a one-to-many relationship.
- Authorization and authentication: In the routes of the sample project, there is no authorization required. In a real app, you’d protect the routes according to the user or admin permissions.
- SQLite Database: This tutorial uses an on-disk SQLite database. In later stages of development, and certainly in production, you should use a scalable database running on a dedicated server. Good choices include PostgreSQL and MySQL.
Understanding and Configuring APNS
Now that you understand the differences between this sample project and one you could put into production, it’s time to take a look at how to set up APNS.
APNS Device Registration Flow
Apple’s documentation defines APNS in the following way:
The guide also mentions providers, which are the server counterparts of your app. They have three responsibilities:
- Receiving and storing the device tokens, which belong to instances of your app.
- Determining when and what to send to each device.
- Building and sending the payload to APNS containing the delivery information.
The figure below explains these steps:
Here’s the run down:
1A. Your app registers for remote notifications with APNS by calling
1B. APNS creates a unique device token and your app receives it via
1C. Your app converts the device token from
String and issues a request to your server to store it in the database.
2. Your server decides when the appropriate moment to send the notification is.
3A. The server builds the notification payload and submits it to APNS (for each device).
3B. APNS delivers the notification to the device.
Creating the APNS Push Key
Apple introduced push notifications with iOS 3. At that time, servers used a single certificate, exported as a .p12 file, to authenticate with APNS. Developers had to manually generate these certificates for each app in the Developer Portal and they were only valid for one year.
In 2016, Apple added a better way to manage authenticating with APNS: token-based connections, which use signing keys. In this context, the authentication token has no relationship with a device token.
This mechanism has a few advantages over certificates. The main one is that your server can use the same token to send notifications to multiple apps you own. Another advantage is that the key doesn’t expire, although it’s a good practice to revoke it and use a new one every once in a while.
Because this is now the recommended method, this tutorial uses an APNS key. To start generating one, go to https://developer.apple.com and log in with your credentials. In the left panel, under Program Resources, click Certificates, IDs & Profiles. In the left menu again, click Keys, then click the Plus button.
The Register a New Key page will load. Give your key a name and select the APNS checkbox:
Click Continue then click Register to confirm:
Once you’ve registered the new key, a Download button will appear. Download the file and use a text editor to open the key and copy the content.
Notice that the file name includes a ten character long identifier: This is the key identifier.
You now have everything you need to configure your server in the next section.