【iOS / Swift】PUSH通知を通知センターに表示する前に、PUSH通知の内容を更新してから表示する方法
PUSH通知を通知センターに表示する前に、PUSH通知の内容を更新してから表示する方法
概要
Notification Service Extensionの使用方法をまとめました。
きっかけ
アプリにて、PUSH通知ペイロードのbodyテキストを更新してから通知センターに表示して欲しい、という要望がありました。
また、アプリがフォアグラウンド・バックグラウンド・未起動時全てで本文更新処理をして欲しいとのことだったので調査・実装しました。
Notification Service Extension
PUSH通知のペイロードを更新して通知センターに表示するためにはNotification Service Extension
を使用する必要があります。
まずはプロジェクトにNotification Service Extension
を追加します。
-
File > New > Targetを選択します。
-
Notification Service Extension
を選択します。
-
Product NameにNotificationServiceと入力して
Finish
をクリックする
以上の操作で、Notification Service Extensionがプロジェクトに追加されました。
(Target追加となるため、プロジェクトによってはNotification Service Extension用の証明書の作成が必要になります。)
注意点
Notification Service Extension
を起動するには、通知ペイロードにaps.mutable-content
属性を指定する必要があります。
/// サンプル
{
"aps": {
"alert": {
"title": "Title",
"body": "Body"
},
"mutable-content": 1 // mutable-content属性を1に指定
}
}
実装
先ほどNotificationService
を追加したことにより、プロジェクトにNotificationService.swift
というファイルが作成されます。
NotificationService
はUNNotificationServiceExtension
を継承しており、下記メソッドが用意されています。
-
didReceive(_:, withContentHandler:)
:PUSH通知が端末に届いたタイミングで呼ばれます。 -
serviceExtensionTimeWillExpire
:上のdidReceive(_:withContentHandler:)
の処理がタイムアウト(30秒)した場合に呼ばれます。
ペイロードのbodyを更新する
didReceive
メソッドでペイロードのbodyを取り出し・更新します。
今回は「;(セミコロン)」に対して「\n(改行コード)」に変換する処理を行っています。
// PUSH通知が届いた時に呼び出される
override func didReceive(_ request: UNNotificationRequest,
withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
if let bestAttemptContent: UNMutableNotificationContent = bestAttemptContent {
// 現在の本文を取得する
var modifiedBody: String = bestAttemptContent.body
// 置換処理を実行
modifiedBody = modifiedBody.replacingOccurrences(of: ";", with: "\n")
// 修正した本文をセット
bestAttemptContent.body = modifiedBody
contentHandler(bestAttemptContent)
}
}
こちらを実装後にPUSH通知を送信してみると、アプリのフォアグラウンド・バックグラウンド・未起動時にPUSH通知に表示されるテキストが変換されているはずです。
さいごに
今回はbody(本文)に対して変換処理をかけていますが、title(タイトル)に対しても可能です。
以下NotificationService.swfitのソースコードになります。
import UserNotifications
// PUSH通知内容の変更を行うエクステエンション
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
// PUSH通知が届いた時に呼び出される
override func didReceive(_ request: UNNotificationRequest,
withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
if let bestAttemptContent: UNMutableNotificationContent = bestAttemptContent {
// 現在の本文を取得する
var modifiedBody: String = bestAttemptContent.body
// 置換処理を実行
modifiedBody = modifiedBody.replacingOccurrences(of: ";", with: "\n")
// 修正した本文をセット
bestAttemptContent.body = modifiedBody
contentHandler(bestAttemptContent)
}
}
override func serviceExtensionTimeWillExpire() {
if let contentHandler: ((UNNotificationContent) -> Void) = contentHandler,
let bestAttemptContent: UNMutableNotificationContent = bestAttemptContent {
contentHandler(bestAttemptContent)
}
}
}
Discussion