すっさんぽ
  1. Posts/

[iOS] プッシュ通知のセットアップから実装するメソッドまとめ

·

プッシュ通知を使用するアプリは、これまでも何度か実装してきたのですが、使用するメソッドなどが曖昧なまま実装していました。 改めてゼロからセットアップしながら、プッシュ通知の実装方法、実装するメソッドをまとめます。

プッシュ通知で登場する3つの通知 #

はじめに、プッシュ通知関連の用語を整理します。 特に以下の3種類の言葉を使い分けることで、機能の理解がぐっと深まります。

リモート通知・リモートプッシュ(Remote Notification)
Appleのプッシュ通知基盤である「APNs」を介して、開発者側からユーザーの端末にデータを通知する仕組みのこと。
ローカル通知(Local Notification)
時刻やタイマー・位置情報などのトリガーに発火する通知のこと。端末内で完結する通知のこと。
ユーザー通知(User Notification)
ユーザーを巻き込んだ通知のこと。音や振動をともなって、画面の上部にバナーが表示されたり、通知センターにアイテムが表示されたりする。

これらのなかでも、特に「リモート通知」による「ユーザー通知」のことが「プッシュ通知」と呼ばれています。この投稿でも、リモート通知でユーザー通知をする方法を扱います。

それでは、セットアップと実装を進めていきます。

ユーザー通知の許可を求める #

まず、ユーザー通知の許可を求めます。この許可を得る作業は「通知センターやバナーで情報を表示すること = ユーザーの邪魔をすること」に対して許可を求めるものであって、リモート通知の許可を得ているわけではありません。通知する情報がたどってくる「経路」と、通知の「表示」は区別して考えます。

  • リモート通知に許諾は不要です、後述のCapability追加でセットアップします。
  • バックグラウンドプッシュのみの場合は、この作業は不要です。

実装するコードは以下のコードです。

// ViewControllerなどに実装する

import UserNotifications

let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .badge, .sound]) { [weak self] granted, error in
    // grantedやerrorを使用して、後続処理を実装する
}

この実装によって、いつもの通知許諾のアラートダイアログを表示することができます。

ちなみに、optionsにつけられる値もいくつかあるので見ておきます。

badge
アプリアイコンに数字のバッジ(赤丸)をつけられる
sound
音を鳴らすことができる
alert
アラート(通知)を画面に表示する
providesAppNotificationSettings
設定アプリから、アプリ内の通知設定画面へ誘導できるようになる(後述)
provisional
通知のお試し期間を設けられる。通知センターの通知アイテムに「このアプリからの通知をまだ受けますか」と表示される。(後述)

soundだけbadgeだけというのはあまり見かけません。 ほとんどは、.alert, .sound, .badgeを指定します。通知がそれほど重要ではないアプリ(たとえばプロモーションだけなど)の場合は、 .provisionalを使うこともあるかもしれません。

.provisionalを指定したときの挙動 #

requestAuthorizationoptions.provisionalを指定した場合は、ユーザー通知の許諾ダイアログは表示されません。 その代わり、requestAuthorizationメソッドを実行したタイミングで、すぐに通知が許可されます。 ただし、通知は、通知センターにしか表示されません。(バナー・サウンド・バッジは無い)

「通知の受信を続けますか?」という選択肢とともに、通知センターに表示されます。

「通知の受信を続けますか?」という選択肢とともに、通知センターに表示されます。

このときの通知設定状況は「目立たない形で配信」になっています。ユーザーが通知に気づくまでは、邪魔にならないようにしているようです。

このときの通知設定状況は「目立たない形で配信」になっています。ユーザーが通知に気づくまでは、邪魔にならないようにしているようです。

通知の表示設定は、通知センターのみになっています。

通知の表示設定は、通知センターのみになっています。

通知センターの通知から、通知の受信を「続ける」を選択すると、「すぐに配信」か「時刻指定要約で配信」を選べます(iOS 15から)。

「すぐに配信」を選択しても、バナーやサウンドの許可状態は変わらないようです。 ユーザーが、設定アプリでバナーやサウンドの許可をする必要があります。

もし通知センターで通知を「オフにする…」をタップすると、アクションシートが表示され「通知をすべてオフにする」を選択することになります。 もし、requestAuthorization.providesAppNotificationSettingsの指定も入れていた場合は、アプリの通知設定画面へ誘導するボタンも追加されます。

タップするとアプリが起動します。

タップするとアプリが起動します。

.providesAppNotificationSettingsを指定したときの挙動 #

設定アプリの通知設定画面に、アプリ内の通知設定画面へ誘導するボタンが表示されるようになります。

タップするとアプリが起動します。

タップするとアプリが起動します。

リモート通知をセットアップする 1: 端末とAPNsの連携 #

ユーザー通知の許諾を実装したら、次はリモート通知をセットアップしていきます。ここからはまず、端末とAPNsを連携させる部分を行います。

Push NotificationをCapablityに追加する #

リモート通知を使用できるようにするため、アプリのターゲットに対してPush NotificationのCapabilityを追加します。 プロビジョニングプロファイルを自動で設定している場合は、このタイミングでプロビジョニングプロファイルが更新されます。

リモート通知を受信できるようにするため、APNsに端末を登録する #

CapabilityにPush Notificationを追加できたら、次はAPNsからリモート通知を受信できるようにするため、以下の実装を追加します。

import UIKit

// ViewControllerやAppDelegateなどで

UIApplication.shared.registerForRemoteNotifications()

これを呼び出すタイミングに特別な指定はなく、APNsに端末を登録したくなったタイミングで行います。 よく見かける実装では、最初に実装したUNUserNotificationCenter.current().requestAuthorization(options:completionHandler)メソッドのCompletion Handler内で行うことが多いです。

ただし、registerForRemoteNotificationsrequestAuthorizationは区別して考えてください。「リモート通知」を受けるためにAPNsに端末を登録することと、「ユーザー通知」の許可を得ることは、別のものです。 ユーザー通知の許可を得ないとAPNsに端末を登録できないのではありません。ユーザー通知の許可を得ていなくても、バックグラウンド通知は受信することができます。

バックグラウンドプッシュ(サイレントプッシュ)する場合は、registerForRemoteNotificationsを呼ぶだけで十分です。AppDelegatedidFinishLaunchingWithOptionsなどの初期化処理のうちに済ませるのが都合が良さそうです。

参考

デバイストークンを受け取る #

registerForRemoteNotifications()を呼んだので、次はデバイストークンを受け取ります。実装するメソッドは以下のとおりです。

  • application(_:didRegisterForRemoteNotificationsWithDeviceToken)
  • application(_:didFailToRegisterForRemoteNotificationsWithError)

ここは定型文で良いでしょう。

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    let tokenParts = deviceToken.map { data -> String in
        return String(format: "%02.2hhx", data)
    }
    let token = tokenParts.joined()
    logger.info("Device Token: \(token)")

    // 自身の管理するサーバにトークンを送信するなど、トークンを保持する作業をします
    // Appleのドキュメントでは、トークンはローカルに置かないようにしましょうとのこと。
}

func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
    logger.error("Failed to register for remote notifications with error: \(error.localizedDescription)")
}

ここまでの作業で、端末とAPNsを連携させる部分が実装できました。

参考

リモート通知をセットアップする 2: サーバとAPNsの連携 #

次は、自身の管理するサーバやFirebase・AWSなどのマネージドサービスと、APNsを連携させていきます。

リモートプッシュの証明書またはキーを作成する #

サーバからAPNsへの通信には、証明書(p12)による署名またはキー(p8)による暗号化が必要です。 Apple Developerのサイトへログインしたら、証明書を使用する場合は「Identifiers」から、キーを使用する場合は「Keys」のメニューから行います。 どちらを選ぶかは、今後の運用方法なども考慮して決めると良いでしょう。

証明書(p12) キー(p8)
適用範囲 AppIDごと 1チーム(開発者)で共通
更新の有無 あり(1年に1回) なし(同じキーを永続使用)
紛失時の再発行 あり(秘密鍵は紛失しないことが条件) なし(紛失時は再作成)
証明書・鍵交換時のダウンタイム なし(証明書は2つ作れるので、ダウンタイム無しで交換できる。p12ファイルの差し替えでOK) あり(キーの再作成時にダウンタイムが発生する)

詳しい作成方法は、以下のリンクを参考にすると良さそうです。

参考

ちなみに今回は、証明書を使う方でセットアップしてみました。

App IDをクリックします。

App IDをクリックします。

DevelopmentまたはProduction、必要な方を選択します。

DevelopmentまたはProduction、必要な方を選択します。

証明書の種類による違いは、以下のとおりです。

タイプ ビルド
Development証明書 Debug、AdHoc
Production証明書 Release
CSRをキーチェンアクセスから作成します。

CSRをキーチェンアクセスから作成します。

「通称」に入力した内容は、秘密鍵の名称になるので、アプリ名やDevelopment・Productionなど、わかり易い名前をつけたほうが良いです。

「通称」に入力した内容は、秘密鍵の名称になるので、アプリ名やDevelopment・Productionなど、わかり易い名前をつけたほうが良いです。

こうして作成したCSRを、Apple Developerにアップロードします。すると、証明書が作成され、ダウンロードできるようになります。 必要に応じて、ローカルにインストールしたり、Firebase・AWSのプッシュ管理サービスに設置します。

これで、サーバとAPNsの連携作業は完了です。

プッシュしてみる #

では実際にプッシュが届くか、試してみたいと思います。 ここでは「Knuff」というアプリケーションから、プッシュのデータをAPNsに投げてみます。 Knuffよりも「Pusher」というアプリがよく使われている印象ですが、APNsにデータ送信ができなくなっていました。今回はKnuffを使います。

署名に使用する証明書を選択し、Tokenを入力します。 その上で、プッシュのペイロードを入力して、プッシュします。

プッシュ通知が届きました!

プッシュ通知が届きました!

バッジも付いています。

バッジも付いています。

画像では見えませんが、ちゃんと音も鳴ります。

これで、プッシュ通知を端末に送ることができるようになりました!


まとめ #

プッシュ通知をセットアップ・実装する方法をまとめました。 次回は、バックグラウンドプッシュへの対応・画像や動画のついたリッチコンテンツへの対応をまとめます。