APIサーバーをSwiftで構築できるようになった今、プッシュ通知用のサーバーもSwiftで構築したい!ということがあるかもしれません。そこで「VaporAPNS」です。
この記事ではVaporAPNSを使ってプッシュ通知を送る方法を紹介します。実際はデバイストークンを受け取ってDBに保存したりしますが、その部分は省きデバイストークンが分かっている前提で紹介します。デバイストークンを受け取るサーバー自体もVaporで簡単に実装できるのでぜひ試してみてください。
環境
以下の環境で検証しました。
- OS X El Capitan 10.11.5
- Swift 3.0.1
- VaporAPNS 1.1.1
- iOS 10.1
準備
HTTP/2
APNs Provider APIを利用するためにHTTP/2に対応したクライアントが必要なため以下のようにします。
$ brew reinstall curl --with-openssl --with-nghttp2
$ brew link curl --force
証明書
APNsとの通信に使用する証明書を準備します。証明書の作成方法は検索すれば沢山ヒットするため省きます。新しくAuthentication Keyを使って認証する方式もありますが、そちらについてはこの記事では触れません。検証してはいませんが、VaporAPNSのドキュメントには、Authentication Keyを使った方法についても触れているので確認してみてください。
従来方式を使用する場合は以下のようにしてp12ファイルから証明書と秘密鍵を取り出してください。
$ openssl pkcs12 -in Certificates.p12 -out push.crt.pem -clcerts -nokeys
$ openssl pkcs12 -in Certificates.p12 -out push.key.pem -nocerts -nodes
導入
まずはSwift Package Managerでパッケージを作成します。今回は「vapor-apns」というディレクトリに作成しています。
$ swift package init --type executable
次にPackage.swiftにライブラリの依存関係を記述します。
import PackageDescription
let package = Package(
name: "vapor-apns",
dependencies: [
.Package(url:"https://github.com/matthijs2704/vapor-apns.git", majorVersion: 1, minor: 1)
]
)
フェッチします。
$ swift package fetch
次に必須ではないですがXcodeのプロジェクトファイルを生成します。Xcodeを使うと普段アプリを開発している環境でサーバーも実装できるので便利です。
$ swift package generate-xcodeproj
実装
次にVaporAPNSを使って実際にプッシュ通知を受け取る実装をします。main.swiftに
import VaporAPNS
let devicetToken = "デバイストークン"
let options = try! Options(topic: "バンドルID", certPath: "証明書のパス", keyPath: "秘密鍵のパス")
let vaporAPNS = try VaporAPNS(options: options)
let payload = Payload(message: "hoge")
let pushMessage = ApplePushMessage(priority: .immediately, payload: payload)
vaporAPNS.send(pushMessage, to: devicetToken)
こんな感じのコードを実装します。アプリ側では、
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
let center = UNUserNotificationCenter.current()
center.delegate = self
center.requestAuthorization(options: [.badge, .sound, .alert]){ isGranded, _ in
if isGranded {
application.registerForRemoteNotifications()
}
}
return true
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let characterSet = CharacterSet(charactersIn: "<>")
let deviceToken = String(format: "%@", deviceToken as CVarArg)
.trimmingCharacters(in: characterSet)
.replacingOccurrences(of: " ", with: "")
print("deviceToken: \(deviceToken)")
}
}
extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.badge, .sound, .alert])
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
completionHandler()
}
}
こんな感じに実装して、端末にインストールします。
あとはコンパイルして実行するだけです。
$ swift build
$ .build/debug/vapor-apns
結果
やりました。