プッシュ通知(Swift)
基本的な使い方(Swift UI App版)
Contents |
概要
このページでは、プッシュ通知の基本的な使い方について説明していきます。
設定の流れ
ニフクラ mobile backendのプッシュ通知機能は、
Appleが提供しているApple Push Notification Service(以下、APNs)
と連携することで、通知の配信を行っています。
Swiftアプリでプッシュ通知を受信するまでの設定は以下のような流れとなっています。
- APNsの設定と証明書の取得
- ニフクラ mobile backendでの設定
- アプリでの設定
APNsの設定とニフクラ mobile backendへの設定
まずはじめに、Appleの開発者サイトでAPNsを有効にして、
ニフクラ mobile backendと連携させるための証明書を取得する必要があります。
以下のドキュメントを参考に、 p12証明書、p8認証キーどちらかの方法で
Appleの開発者サイトでの設定とニフクラ mobile backendへの設定を行ってください。
アプリでの設定
アプリ側では、端末をニフクラ mobile backendに登録する処理を
実装していきます。
なお、ニフクラ mobile backendのSwift SDKは
インストールと初期化が済んでいるものとして説明しますので、
未実施の場合はクイックスタートをご覧ください。
Xcodeでの対応
TARGETS -> 「Signing & Capabilities」を選択し、「+ Capability」をクリックします。
Push Notifications を検索し、ダブルクリックして追加します。
再度「+ Capability」をクリックして、 Background Modesを検索し、ダブルクリックして追加します。
Remote notifications機能をチェックを入れて、有効にしてください。
正常に追加されましたら、Signing情報の下に Push Notifications と Background Modesが表示されます。
次にBundleIDとプロビジョニングファイルを設定します。
Signing & Capabilities
画面 でBundle Identifier
を入力します。Provisioning Profile
のところでImport Profile
のボタンを押してプロビジョニングファイルをインポートします。
配信端末情報の登録
APNsでは、プッシュ通知の配信端末を一意に識別するDevice Tokenを利用し、
各端末への配信を行っています。
そのため、APNsからDevice Tokenを取得したあとで、
データストアに配信端末情報として登録する必要があります。
AppDelegateクラス内のapplication:didFinishLaunchingWithOptionsメソッド内で
Device Tokenの要求をAPNsに対して行います。
・サンプルコード
Frameworkのimportが必要となります。
// APP_NAME.swift
import UserNotifications
@main
struct SwiftApp: App {
// Link AppDelegate to App
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
///////////////////////////AppDelegate クラスを追加///////////////////////////////
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in })
application.registerForRemoteNotifications()
return true
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print(error.localizedDescription)
}
}
Device Tokenが取得できた場合は、同じAppDelegate classの
application:didRegisterForRemoteNotificationsWithDeviceTokenメソッド
が呼び出されますので、端末情報をデータストアに登録します。
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
//端末情報を扱うNCMBInstallationのインスタンスを作成
let installation : NCMBInstallation = NCMBInstallation.currentInstallation
//Device Tokenを設定
installation.setDeviceTokenFromData(data: deviceToken)
//端末情報をデータストアに登録
installation.saveInBackground(callback: { result in
switch result {
case .success:
//端末情報の登録が成功した場合の処理
print("保存に成功しました")
case let .failure(error):
//端末情報の登録が失敗した場合の処理
print("保存に失敗しました: \(error)")
return;
}
})
}
次にAppDelegateでNotification CenterとしてUNUserNotificationCenterDelegateという拡張を作成します。ここでは通知受信後の処理について記述します。
iOS10をサポートするため、@available(iOS 10, *)をAttributeとして追記してください。
@available(iOS 10, *)
extension AppDelegate : UNUserNotificationCenterDelegate {
// フォアグラウンド状態で通知を受信して表示する
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
// 任意のプレゼンテーションオプションに変更できます
completionHandler([[.banner, .badge, .sound]])
}
// バックグラウンド状態で通知を受信して表示する
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
completionHandler()
}
}
以上でアプリ側での設定は完了です。
アプリをiOS端末で実行し、端末情報がデータストアに登録されるか確認してください。
アプリの再インストール時を考慮する場合
アプリが再インストールされた場合などに、前回のインストール時に保存された端末情報が
mobile backend上に残ったままの場合が考えられます。
その場合には端末情報の登録でdeviceTokenの重複エラーが発生するため、
エラーが発生したときの処理を実装する必要があります。
端末情報でエラーが発生した場合にエラーコードを取得し、
409001(重複してはいけない値を登録しようとした場合に発生するエラーコード)かを判定し、
データストアに保存されている端末情報を上書きするようにします。
let installation : NCMBInstallation = NCMBInstallation.currentInstallation
installation.setDeviceTokenFromData(data: deviceToken)
installation.saveInBackground(callback: { result in
switch result {
case .success:
//端末情報の登録が成功した場合の処理
break
case let .failure(error):
//端末情報の登録が失敗した場合の処理
let errorCode = (error as! NCMBApiError).errorCode;
if (errorCode == NCMBApiErrorCode.duplication) {
//失敗した原因がdeviceTokenの重複だった場合
self.updateExistInstallation(installation: installation)
} else {
//deviceTokenの重複以外のエラーが返ってきた場合
}
return
}
})
端末情報を上書き保存するupdateExistInstallation:は以下のようにします。
//deviceTokenの重複で端末情報の登録に失敗した場合に上書き処理を行う
func updateExistInstallation(installation: NCMBInstallation) -> Void {
var installationQuery : NCMBQuery<NCMBInstallation> = NCMBInstallation.query
installationQuery.where(field: "deviceToken", equalTo: installation.deviceToken!)
installationQuery.findInBackground(callback: {results in
switch results {
case let .success(data):
//上書き保存する
let searchDevice:NCMBInstallation = data.first!
installation.objectId = searchDevice.objectId
installation.saveInBackground(callback: { result in
switch result {
case .success:
//端末情報更新に成功したときの処理
break
case .failure:
//端末情報更新に失敗したときの処理
break
}
})
case .failure:
//端末情報検索に失敗した場合の処理
break
}
})
installationが削除された時を考慮する場合
以下の例のように、何らかの理由により有効な installation が削除されてしまった場合、通常の実装では installation の再登録は行われず、該当の端末へはプッシュ通知を配信することができなくなってしまいます。
- 管理者の操作ミスによる削除
- コントロールパネル上の操作ミスなど
- 管理者が意図しない操作による削除
- mobile backend ではアプリがアンインストールされた端末情報(installation)の自動削除機能において、Feedbackサービスで返却される「無効なデバイストークン」を削除しています。 「有効なデバイストークン」であっても、APNs の判断で返却された場合は、mobile backend 側では削除対象となります。
そのため、 installation を再度登録するには、以下の処理を追加実装する必要があります。
let installation : NCMBInstallation = NCMBInstallation.currentInstallation
installation.setDeviceTokenFromData(data: deviceToken)
installation.saveInBackground(callback: { result in
switch result {
case .success:
//端末情報の登録が成功した場合の処理
break
case let .failure(error):
//端末情報の登録が失敗した場合の処理
let errorCode = (error as! NCMBApiError).errorCode;
if (errorCode == NCMBApiErrorCode.noDataAvailable) {
//失敗した原因がdeviceTokenの該当データが無い場合
self.reRegistInstallation(installation: installation)
} else {
//deviceTokenの該当データが無いエラー以外が返ってきた場合
}
return
}
})
installation が削除された場合(端末情報の該当データがmoble backend 上に存在しない場合)は、以下のように installation を再作成します。
//mobile backend上に該当データがない場合に新規作成処理を行う
func reRegistInstallation(installation: NCMBInstallation) -> Void {
//objectIdのみ削除し、installationが再生成されるようにする
installation.objectId = nil
//端末情報をデータストアに登録
installation.saveInBackground(callback: { result in
switch result {
case .success:
//端末情報の登録が成功した場合の処理
break
case let .failure(error):
//端末情報の登録が失敗した場合の処理
break
}
})
}
プッシュ通知をアプリから送信する
管理画面だけでなく、アプリからも他の端末へプッシュ通知を送信することができます。
プッシュ通知の設定を行う
iOS端末へのプッシュ通知を行う場合は、バッジの増加フラグや、着信音の設定などが可能です。
content-availableとバッジ数増加フラグは、どちらかしか設定できません。
(参考)REST APIリファレンス:プッシュ通知登録
// プッシュ通知オブジェクトの作成
let push : NCMBPush = NCMBPush()
push.sound = "default"
push.badgeIncrementFlag = true
push.contentAvailable = false
push.message = "プッシュ通知です" //メッセージの設定
push.isSendToIOS = true //iOS端末を送信対象に設定する
push.setImmediateDelivery()// 即時配信
// プッシュ通知を配信登録する
push.sendInBackground(callback: { result in
switch result {
case .success:
print("登録に成功しました。プッシュID: \(push.objectId!)")
case let .failure(error):
print("登録に失敗しました: \(error)")
return;
}
})
Android端末へのプッシュ通知を行う場合は、起動画面、ダイアログプッシュ通知の有効フラグを設定できます。
// プッシュ通知オブジェクトの作成
let push : NCMBPush = NCMBPush()
push.message = "プッシュ通知です" //メッセージの設定
push.action = "ReceiveActivity" //アクションの設定
push.title = "testPush" //タイトルの設定
push.isSendToAndroid = true // Android端末を送信対象に設定する
push.setImmediateDelivery() // 即時配信
// プッシュ通知を配信登録する
push.sendInBackground(callback: { result in
switch result {
case .success:
print("登録に成功しました。プッシュID: \(push.objectId!)")
case let .failure(error):
print("登録に失敗しました: \(error)")
return;
}
})
プッシュ通知のスケジューリング
プッシュ通知の配信時刻を指定することができます。
配信時刻を指定するか、即時配信を指定しないと、プッシュ通知を登録することができません。
(参考)REST APIリファレンス:プッシュ通知登録
// プッシュ通知オブジェクトの作成
let push : NCMBPush = NCMBPush()
push.message = "プッシュ通知です" //メッセージの設定
push.isSendToIOS = true //iOS端末を送信対象に設定する
push.isSendToAndroid = true //Android端末を送信対象に設定する
// 配信時刻を設定する
let formatter : DateFormatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
formatter.timeZone = TimeZone(secondsFromGMT: 0)
push.deliveryTime = formatter.date(from: "2020-07-24T10:10:01.964Z")
// プッシュ通知を配信登録する
push.sendInBackground(callback: { result in
switch result {
case .success:
print("登録に成功しました。プッシュID: \(push.objectId!)")
case let .failure(error):
print("登録に失敗しました: \(error)")
return;
}
})
管理画面からプッシュ通知を配信する
ここからは、管理画面からプッシュ通知を配信する方法を説明します。
プッシュ通知を送信する
管理画面左側メニューのプッシュ通知をクリックし、プッシュ通知の画面を開きます。
新しいプッシュ通知ボタンをクリックすると、プッシュ通知作成画面が表示されます。
このページで新たなプッシュ通知を作成できます。タイトル、メッセージ、JSONデータを記入してください。
※プッシュ通知の設定でメッセージを入力しなかった場合は、端末にプッシュ通知が表示されません。
(上記の場合でも、プッシュ通知の受信音の設定、JSONデータの取得は可能です。)
※iOS宛プッシュ通知の設定は、iOS8未満は合計256バイトまで、iOS8以降は合計2Kバイトまでがサポート対象となります。
配信日時の指定を行います。以下の例では、作成されたプッシュ通知が即時に配信される設定になっています。
プッシュ通知送信日時を指定する場合は、配信日時の欄で日時を選択し、希望する日時を指定してください。
配信期限の指定では電源が切れているなどの事情により通知を受け取れなかった端末への再送信期間を設定できます。デフォルトの設定では再送信できる期間が10日間となっていますが1~28日間、1~24時間の間で、期間を指定できます。
また、配信期限を日時で指定する場合は、日時の指定画面が表示されます。
次に、配信を行うプラットフォームを選択してください。AndroidとiOSの両方にプッシュ通知を送信することも可能です。
Androidを選択した場合は、以下のようにアクション設定と、ダイアログ表示の設定画面が表示されます。
iOSを選択した場合は、以下のようなiOS端末へのプッシュ通知を行うための設定画面が開きます。
※「バッジ件数」が「インクリメントする」に設定されている場合はInstallationクラスbadgeフィールドの値に対してインクリメントを実行し、プッシュ通知のパラメータに付加して送信しています。
※「音声ファイル名」が設定されている場合でも、プッシュ通知を受信した際にアプリがフォアグラウンド状態だと通知音が鳴りません。
※設定した「音声ファイル名」が存在しない場合は、デフォルトの通知音が鳴ります。
絞り込みを行いたい場合には、配信端末を「installationクラスから絞り込み」とし、条件を設定してください。
最後に「プッシュ通知を作成する」ボタンをクリックすると、プッシュ通知が作成されます。
テンプレートを使用する
プッシュ通知作成画面上部にあるテンプレート機能では、プッシュ通知作成時に入力・設定した内容を保存しておくことができます。
毎回同一内容のプッシュ通知を作成している場合、テンプレート機能を使用することで、プッシュ作成時の手間を省くことができます。
タイトルやメッセージを入力した後、「テンプレートとして保存する」ボタンをクリックしてください。
すると、以下のようなポップアップが表示されます。
テンプレート名を入力し、「保存する」ボタンをクリックすると、テンプレートとして保存されます。
保存されたテンプレートはプルダウンから選択可能です。
- 注意
- 1アプリにつき20テンプレートの保存が可能です。
- 配信日時、配信期限、パーミッションの内容は、テンプレートとして保存されません。
プッシュ通知の詳細画面について
配信後は、プッシュ通知の詳細画面よりプッシュ通知ID・実際の配信数・配信エラー内容などの情報を確認することが可能です。
プッシュ通知の配信ステータスについて
プッシュ通知一覧の画面では、プッシュ通知のタイトルの右側に、配信ステータスが表示されます。
こちらのステータスが「未配信」、「配信済み」、「配信中」以外だった場合、プッシュ通知の配信が失敗した端末が存在しています。
配信ステータスの詳細は こちらの「プッシュ通知のステータスについて」項目にてご参考ください。
※以下の画像では、「配信済み(一部エラー)」と表示されている部分がステータスに該当します。
配信ステータスが「配信済み(一部エラー)」の場合は、該当のプッシュ通知をクリックすると表示される、画面右側のプッシュ通知詳細画面最下部の「配信エラー内容」にエラーの詳細が出力されていますので、ご確認ください。
また、配信ステータスが「配信エラー」になる場合の主な理由と対策は、以下の通りです。
- iOS証明書の不具合
- iOS証明書を再設定し、端末情報を再度登録したうえで、プッシュ通知をテストしてください。
- iOS証明書の有効期限が切れている場合は、証明書を更新してください。※iOS証明書の有効期限切れについては、こちらもご参考ください。
- iOS証明書またはAndroidプッシュ通知設定ファイルを設定していないのに、両方のOSを対象にしてプッシュ通知を登録
- 配信対象はデフォルトでiOS/Androidの両方なので、iOS証明書とAndroidプッシュ通知設定ファイルをどちらも設定していないとエラーになります。
配信エラーとなった場合に、管理画面からmobile backend側のログについて
確認することはできませんので、ご不明な点がございましたらお気軽にお問い合わせください。
ダミーデータを登録した端末を指定してプッシュ通知を行わない
プッシュ通知を配信する端末の中に、
テスト目的などでダミーデータを入力した端末が含まれていると、
他の端末も含めてプッシュ通知が配信されない場合がございます。
アプリ側でプッシュ通知が受信されるかを確認する場合は、
ダミーデータを含んだ端末を配信対象に含めないでください。
過去のプッシュ通知データについて
プッシュ通知配信履歴自動バックアップ機能によってバックアップされたデータは、「過去のプッシュ通知データ一覧」画面にてダウンロード/削除が可能です。
プッシュ通知配信履歴自動バックアップ機能
プッシュ通知の配信に伴い、配信済みのプッシュ通知オブジェクトは内部データベースに累積いたします。
こちらはプッシュ通知の登録ごとに作成されますので、個通のプッシュ通知を多用されるなど、プッシュ通知登録数が多い場合につきましては、オブジェクトの容量肥大が考えられます。
容量が肥大しますと、プッシュ通知の配信パフォーマンス低下やストレージ容量の逼迫に繋がります。
上記現象を防ぐため、プッシュ通知オブジェクトが約100万件(※)を超過した場合、超過分の配信済みのプッシュ通知オブジェクト(開封率データ含む)は自動でバックアップされます。
※レコード件数ではなく、データサイズ(非公開情報)での制限を設けているため、約100万件の制限と表記しております。
- バックアップデータ(CSV)は管理画面よりダウンロード/削除が可能です。
- バックアップデータは、プッシュ通知データの場合は配信時刻(JST)の年月ごとにファイルが分けられ、
push_YYYYMM.csv
という形式のファイル名となります。開封率データの場合は登録日時(JST)の年月ごとにファイルが分けられ、push_open_state_YYYYMM.csv
という形式のファイル名となります。例としてプッシュ通知の配信時刻が 2022年3月15日09:00(JST)だった場合、そのデータはpush_202203.csv
というファイル名のファイルに出力されます。 - バックアップデータは、API経由でのアクセスは行えません。 (該当プッシュ通知データへのアクセスもしくは開封通知登録を行った場合、E404001エラーが返却されます)
以上より、配信済みのプッシュ通知オブジェクトへAPIアクセスする処理を組み込まれる場合は、自動バックアップによりエラーが発生する可能性があることを考慮した実装をお願いいたします。
過去のプッシュ通知データに関する注意事項
- バックアップデータの容量も、ストレージ容量にカウントされます。
- バックアップデータはエクスポート機能のエクスポート対象外です。
- バックアップデータ内のデータには、APIアクセスできません。
- 自動バックアップは内部で随時行われています(実施タイミングについては非公開)ので、以下の点にご注意ください。
- 自動バックアップが行われている際に削除されたプッシュ通知データについては、バックアップデータ(CSV)に存在する可能性がございます。何卒ご了承ください。
- 一度ダウンロードされたバックアップデータであっても、中身が更新されていることがございます。削除する際には必ず最新版のバックアップデータをダウンロードしておくことを推奨いたします。一度削除してしまったバックアップデータの復元は不可能ですので、ご注意ください。(有償での復元対応も致しかねます。)
プッシュ通知でJSONデータを取得する
プッシュ通知にはJSON形式で任意のデータを含めることができるので、
通知を受信した時に、そのデータを受け取って処理を行うことができます。
アプリの状態によって、プッシュ通知を受信したときのメソッドが異なっており、
ペイロードを取得するためのキーも名前が違ってきます。
※注意
iOS 13.6以降で確認した場合、アプリがバックグラウンドにいる状態、ペイロードを取得するために、配信を登録する際、content-availableをtrue指定する必要があります。
なお、アプリはフォアグラウンドにいる場合、content-availableがfalseでも取得可能となっています。
プッシュ通知の情報(ペイロード)からデータを取得する
extension AppDelegate : UNUserNotificationCenterDelegate {
// フォアグラウンド状態で通知を受信して表示する
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
// userInfoにプッシュ通知の情報(ペイロード)を取得
let userInfo = notification.request.content.userInfo
print(userInfo)
completionHandler([[.banner, .badge, .sound]])
}
// バックグラウンド状態で通知を受信して表示する
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
// userInfoにプッシュ通知の情報(ペイロード)を取得
let userInfo = response.notification.request.content.userInfo
print(userInfo)
completionHandler()
}
}
ペイロードの内容について
iOS端末へのプッシュ通知では、以下のペイロードが受信されます。
パラメータ名 | 説明 | データ型 |
---|---|---|
com.nifcloud.mbaas.PushId | プッシュ通知ID | 16文字の文字列 |
com.nifcloud.mbaas.RichUrl | リッチプッシュ通知用URL | 文字列 |
aps | プッシュ通知の設定(別表) | オブジェクト |
- | ユーザー設定値 | オブジェクト |
apsには通知音やバッジ数についての設定が含まれています。
パラメータ名 | 説明 | データ型 |
---|---|---|
sound | プッシュ通知音のファイル名 | 文字列 |
alert | タイトル、メッセージ | オブジェクト |
category | アクション用のカテゴリ名 | 文字列 |
badge | バッジ数 | 数値 |
content-available | バックグラウンド通知フラグ | 1 |
JSONデータのパラメータに使用可能な文字の制限
JSONデータのパラメータには、以下の文字が使用できません。
- ダブルクォーテーション「"」
- ドット「.」
- 先頭にドル記号「$」
お探しの内容が見つからなかった場合はユーザーコミュニティ
もご活用ください。(回答保証はいたしかねます)
なお、 Expertプラン以上のお客様はテクニカルサポートにてご質問を承らせて頂きます。
推奨画面サイズ1024×768px以上