1. rb-de0

    Posted

    rb-de0
Changes in title
+VaporAPNSを使ってプッシュ通知を送る
Changes in tags
Changes in body
Source | HTML | Preview

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

結果

やりました。

参考