Open10

iOSのプッシュ通知(リモート通知)について

kamimikamimi

プッシュ通知(リモート通知)とは

  • アプリが実行していない時でも、アプリを使用するデバイスにデータを通知することで、ユーザに情報を提供する
    • ユーザにアクションを促す通知だけではなく、バックグラウンドで動作するバックグラウンド更新のプッシュもある(後述)


kamimikamimi

1. デバイストークンを送る

  • デバイストークン
    • APNsに登録する、グローバルで一意なトークン。デバイス上のアプリのアドレス。
    • アプリを起動する度に、アプリを登録し、デバイストークンを受け取る
func application(_ application: UIApplication,
           didFinishLaunchingWithOptions launchOptions:
           [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
   // Override point for customization after application launch.you’re         
   UIApplication.shared.registerForRemoteNotifications()
   return true
}

func application(_ application: UIApplication,
            didRegisterForRemoteNotificationsWithDeviceToken 
                deviceToken: Data) {
   self.sendDeviceTokenToServer(data: deviceToken)
}

func application(_ application: UIApplication,
            didFailToRegisterForRemoteNotificationsWithError 
                error: Error) {
   // Try again later.
}

https://developer.apple.com/documentation/usernotifications/registering_your_app_with_apns

kamimikamimi

2. プッシュ情報を送信(POSTリクエスト)

  • POSTでリクエストするときには、以下の情報を含める
    • JSONペイロード
    • デバイストークン
    • 通知の配信方法を指定するリクエストヘッダー
    • (トークンベースの認証の場合)プロバイダーサーバの現在の認証トークン

認証トークンでリクエストする場合の例

HEADERS
  - END_STREAM
  + END_HEADERS
  :method = POST
  :scheme = https
  :path = /3/device/00fc13adff785122b4ad28809a3420982341241421348097878e577c991de8f0
  host = api.sandbox.push.apple.com
  authorization = bearer eyAia2lkIjogIjhZTDNHM1JSWDciIH0.eyAiaXNzIjogIkM4Nk5WOUpYM0QiLCAiaWF0I
		 jogIjE0NTkxNDM1ODA2NTAiIH0.MEYCIQDzqyahmH1rz1s-LFNkylXEa2lZ_aOCX4daxxTZkVEGzwIhALvkClnx5m5eAT6
		 Lxw7LZtEQcH6JENhJTMArwLf3sXwi
  apns-id = eabeae54-14a8-11e5-b60b-1697f925ec7b
  apns-push-type = alert
  apns-expiration = 0
  apns-priority = 10
  apns-topic = com.example.MyApp
DATA
  + END_STREAM
  { "aps" : { "alert" : "Hello" } }

JSONペイロード

  • リクエストの本文に入れる
{
   "aps" : {
      "badge" : 9,  // アプリアイコンにつくバッジ
      "sound" : "bingbong.aiff"  // 再生するサウンド
      "alert" : {
         "title" : "Game Request",  // プッシュ通知のタイトル
         "subtitle" : "Five Card Draw",  // プッシュ通知のサブタイトル
         "body" : "Bob wants to play poker"  // プッシュ通知の本文
      },
      "category" : "GAME_INVITATION"  // 何じゃこりゃ
   },
   "gameID" : "12345678"  // カスタムキー(自由に設定できるキー)
}

通知の配信方法を指定するリクエストヘッダー

フィールド 必須/任意 説明
method 🟢 POST
path 🟢 デバイストークンへのパス。
authorization (トークンベースの認証の場合は必要) bearer <provider_token>
apns-push-type (watchOS 6 以降では必須。macOS、iOS、tvOS、および iPadOS では推奨) payloadの内容を正確に反映する
apns-id 通知の一意なUUID。エラーが発生した場合、この値がレスポンスされる。このヘッダーが省略された場合は、APNsが自動でUUIDを作成してレスポンスする。
apns-expiration 通知が無効になる日付。値がゼロ以外の場合、APNs は通知を保存し、少なくとも 1 回配信を試み、指定された日付まで必要に応じて配信を試みる。値が0の場合、APNs は通知の配信を 1 回だけ試行し、保存しない。
apns-priority 通知の優先度。省略するとAPNsは10を設定する。
10:通知をすぐに配信する
5:ユーザのデバイスの電源に関する考慮をして通知を配信する
1:配信よりもデバイスの電源に関する考慮をし、デバイスが起動するのを防ぐ
apns-topic (トークンベースの認証の場合は必要) 通知のトピック。通常はアプリのBundle IDかアプリID。
apns-collapse-id 複数の通知をユーザ向けの一つの通知に結合するために使用される識別子。同じ通知を複数回送信する場合は、このヘッダーで同じ値を使用してリクエストを結合する。

apns-push-typeの種類

種類 説明
alert アラート、バッジ、サウンドなど、ユーザインタラクションをトリガーする通知。
background backgroundバックグラウンドでコンテンツを配信し、ユーザー インタラクションをトリガーしない通知。
location ユーザーの位置情報を要求する通知。
voip Voice-over-IP (VoIP) 通話の着信に関する情報を提供する通知。
complication watchOS アプリのコンプリケーションの更新情報を含む通知。
fileprovider ファイル プロバイダー拡張機能への変更を通知
mdm mdm管理対象デバイスに MDM サーバーに接続するように指示する通知。

https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns

APNsとの接続の確立方法

  1. トークンベース

https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/establishing_a_token-based_connection_to_apns

  1. 証明書ベース

https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/establishing_a_certificate-based_connection_to_apns

kamimikamimi

4.レスポンスを返却する

  • 成功した場合
HEADERS
  + END_STREAM
  + END_HEADERS
  apns-id = eabeae54-14a8-11e5-b60b-1697f925ec7b  // リクエストヘッダーにある値と同じ
  :status = 200  // ステータスコード
  • 失敗した場合
HEADERS
  - END_STREAM
  + END_HEADERS
  :status = 400
  content-type = application/json
  apns-id: <a_UUID>
DATA
  + END_STREAM
  { "reason" : "BadDeviceToken" }  // reasonは、失敗の理由を示すエラー コード

https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/handling_notification_responses_from_apns

kamimikamimi

バックグラウンド更新のプッシュ

  • アプリのコンテンツがコンテンツが頻繁に変更されない、または不規則な間隔で変更される場合にこの通知を使用する
  • 新しいコンテンツが利用可能になったときに、アプリに通知する
  • アラート表示、サウンド再生、アプリのアイコンにバッジをつけるなどは行わないリモート通知
  • バックグラウンドでアプリを起動し、サーバからのダウンロードを開始してコンテンツを更新する時間を与える

https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/pushing_background_updates_to_your_app

kamimikamimi

プッシュ通知のUIのカスタマイズ

通知センターで表示されるUIをカスタマイズすることができる

右のようにデフォルトのUI部分を非表示にするためには、Info.plistにあるUNNotificationExtensionDefaultContentHiddenのkeyを追加してtrueにする必要がある

https://developer.apple.com/documentation/usernotificationsui/customizing_the_appearance_of_notifications

https://qiita.com/jollyjoester/items/cc7026b1a102405eecdc#リッチ通知カスタムui

kamimikamimi

iOS15以降の変化

  • 通知センターで表示されるバナーのUIが変わっている
    • payloadのtitleが設定されている場合、アプリ名が表示されずtitleの値が代わりに表示される模様(iOS13と14ではアプリ名もtitlesubtitleも表示されていたが、iOS15から変わったみたい)
  • (他にも何かあるかも)

https://blog.pushwoosh.com/blog/ios-15-push-content-design/

https://developer.apple.com/videos/play/wwdc2021/10091/