Help us understand the problem. What is going on with this article?

VaporAPNSを使ってプッシュ通知を送る

More than 3 years have passed since last update.

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

結果

やりました。

参考

rb-de0
都内のどこかでiOSアプリケーション開発しています。Swift楽しいです。
dwango
Born in the net, Connected by the net.
https://dwango.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした