In this tutorial we are going to build our backend service using Vapor. It will be responsible for sending a notification to our iOS application.
Sometimes sending notifications with only text just isn’t quite enough. This is where rich notifications come in. We can add images and videos to our notification to give the user a richer experience directly from their notification center.
From a terminal in your working directory enter the following command to create your Vapor application.
1$ vapor new RichNotifyServer 2 $ cd RichNotifyServer
Now we will build your application before opening it in Xcode. Remember your first build could take some time to complete. Vapor update will make sure that you have the latest packages.
1$ vapor build 2 $ vapor update
Now open your project in Xcode. Remember to open using Xcode you must run the following command in terminal:
$ vapor xcode -y
Also remember to change the run scheme to be the “run” scheme in case it is not already set to this.
We need to add the Pusher Beams package to our Swift Package Manager (SPM). Start by opening the Package.swift
file from the project navigator. This is our dependencies management file, a bit like our Podfile
or Cartfile
in iOS development.
Below the line that gives us our Vapor package dependency:
.package(url: "https://github.com/vapor/vapor.git", from: "3.0.0"),
Add the following to add our Pusher Beams dependency:
.package(url: "git@github.com:pusher/push-notifications-server-swift.git", .branch("master")),
We need to tell SPM what dependencies each target should have. We do this by editing targets section in the same file. Find the line:
.target(name: "App", dependencies: ["FluentSQLite", "Vapor"]),
Edit it so that it becomes:
.target(name: "App", dependencies: ["FluentSQLite", "Vapor", "PushNotifications"]),
We’ve added the name of our dependency to the array of dependencies for the app target. For more information on the dependency visit Beams docs. For more information relating to SPM, refer to Swift package manager. Your Package.swift
file should now look something like this:
1// Package.swift
2 // swift-tools-version:4.0
3 import PackageDescription
4
5 let package = Package(
6 name: "RichNotifyServer",
7 dependencies: [
8 // 💧 A server-side Swift web framework.
9 .package(url: "https://github.com/vapor/vapor.git", from: "3.0.0"),
10 .package(url: "git@github.com:pusher/push-notifications-server-swift.git", .branch("master")),
11 // 🔵 Swift ORM (queries, models, relations, etc) built on SQLite 3.
12 .package(url: "https://github.com/vapor/fluent-sqlite.git", from: "3.0.0")
13 ],
14 targets: [
15 .target(name: "App", dependencies: ["FluentSQLite", "Vapor", "PushNotifications"]),
16 .target(name: "Run", dependencies: ["App"]),
17 .testTarget(name: "AppTests", dependencies: ["App"])
18 ]
19 )
Now we need to close Xcode and install the package and reopen it. It’s best practice in Vapor to create and install files outside of our Xcode project using command line tools and then reopen Xcode using the toolbox command. After closing Xcode run the following command in the terminal in our working directory.
$ swift build
Reopen Xcode by running:
$ vapor xcode -y
Log in or create your Pusher account to access the dashboard to create a new Beams instance.
Complete step one of the iOS setup guide, we will pick up the remainder later on in this tutorial. Press the X to exit the setup guide and you will be returned to your dashboard for that instance. Scroll to the bottom of this page and you will find your Pusher Beams instance ID and secret key, make note of these you will need them later.
Rich notifications allow you to send different types of multi-media content. There are specific types of supported content that you can send. You can find up to date information on those content types here. You should also make note of the maximum size these files can be.
We will be creating a simple application with one post request that we can use in order to send different push notifications using our REST client.
Open your routes.swift
file and replace the contents with the following:
1//../Sources/App/routes.swift
2 import Vapor
3 import Vapor
4 // 1
5 import PushNotifications
6 /// Register your application's routes here.
7 public func routes(_ router: Router) throws {
8 // 2
9 router.post(PushContent.self, at: "push/") { req, data -> String in
10 PushNotificationService.send(content: data)
11 return "Push Success"
12 }
13 }
14
15 // 3
16 struct PushContent: Content {
17 let title: String
18 let message: String
19 let dataURL: String
20 }
21
22 //4
23 class PushNotificationService {
24 class func send(content: PushContent) throws {
25 let pushNotifications = PushNotifications(instanceId: "YOUR_INSTANCE_ID" , secretKey:"YOUR_SECRET_KEY")
26 let interests = ["general"]
27 let publishRequest = [
28 "apns": [
29 "aps": [
30 "alert": [
31 "title": content.title,
32 "body": content.message
33 ],
34 "mutable-content": 1
35 ],
36 "data": [
37 "attachment-url": content.dataURL
38 ]
39 ]
40 ]
41 pushNotifications.publishToInterests(interests, publishRequest, completion: { publishID in
42 print("Published \(publishID)")
43 })
44 }
45 }
"mutable-content"
flag in the data structure, this will be intercepted by our notification service extension in iOS to display the data. Also make note of our "data"
key that includes our data url. Our application will use this information in order to download the image or video that we have sent.Hit the run button in Xcode, you should see a message in the console saying it has started and is listening on http://localhost:8080. Leave this running in the background whilst you complete part two.
We’ve learnt how to add a dependency the Beams server side SDK as a dependency to Vapor and setup a basic route that can publish notifications to an iOS app that has registered for the interest. We’ve learnt about the different types of rich push notifications that can be sent and their limitations.
Now that you have a basic backend setup we need to go ahead and create the iOS application that can display these notifications. Stay tuned for part two!
The source code for this project can be found here.