プッシュ通知(Swift)
基本的な使い方
Contents |
概要
このページでは、プッシュ通知の基本的な使い方について説明していきます。
設定の流れ
ニフクラ mobile backendのプッシュ通知機能は、
Appleが提供しているApple Push Notification Service(以下、APNs)
と連携することで、通知の配信を行っています。
Swiftアプリでプッシュ通知を受信するまでの設定は以下のような流れとなっています。
- APNsの設定と証明書の取得
- ニフクラ mobile backendでの設定
- アプリでの設定
APNsの設定と証明書の取得
まずはじめに、Appleの開発者サイトでAPNsを有効にして、
ニフクラ mobile backendと連携させるための証明書を取得する必要があります。
以下のドキュメントを参考に、Appleの開発者サイトでの設定を行ってください。
ニフクラ mobile backendでの設定
次に、ニフクラ mobile backendでプッシュ通知の設定を行います。
プッシュ通知の有効化
アプリ設定から、左メニューのプッシュ通知の項目を選択してください。
プッシュ通知の許可設定を行う部分があるので、「許可する」に変更して変更を保存してください。
APNs用証明書のアップロード
Appleの開発者サイトで取得した証明書をアップロードすることで、
APNsとニフクラ mobile backendが連携できるようになります。
APNsの証明書は、開発用とリリース用の2種類があります。
以下のように、別の証明書を用意してニフクラ mobile backendに設定する必要があります。
- 開発用:Apple Push Notification service SSL (Sandbox) を選択
- 本番用:Apple Push Notification service SSL (Sandbox & Production) を選択
- 本来は開発用と本番用を兼ねた証明書ですが、ニフクラ mobile backendに設定する場合は本番用として設定してください。
ニフクラ mobile backendに登録される端末情報は、
その時設定されていた証明書と紐付いているため、証明書を変更すると
mobile backendに登録されているデバイストークン(端末固有の文字列)が
無効になってしまい、端末にプッシュ通知が配信されなくなります。
iOSへのプッシュ通知を行う場合は、
開発用とリリース用でニフクラ mobile backend上にアプリを2つ作成し、
それぞれに開発用・リリース用の証明書を設定してください。
※注意
アップロードするファイルの名前にはルールがありますので、ご注意ください。
詳細は、開発ガイドライン:ファイルストアについてをご参照ください。
以上の設定で、ニフクラ mobile backendとAPNsを連携することができました。
ここからは、アプリ側でプッシュ通知を受信するための実装を行っていきます。
アプリでの設定
アプリ側では、端末をニフクラ mobile backendに登録する処理を
実装していきます。
なお、ニフクラ mobile backendのSwift SDKは
インストールと初期化が済んでいるものとして説明しますので、
未実施の場合はクイックスタートをご覧ください。
Xcodeでの対応
TARGETS -> CapabilitiesからPush NotificationsをONに設定してください。
正常に設定された場合、.entitlementsファイルにaps-environmentが追加されます。
Xcode 11の場合、Capability画面が変更されました。設定の「Signing & Capabilities」を選択し、
「+ Capability」をクリックします。Capability 画面から Push Notification を検索し、ダブルクリックして追加します。正常に追加されましたら、Signing情報の下に Push Notification が記載されています。
配信端末情報の登録
APNsでは、プッシュ通知の配信端末を一意に識別するDevice Tokenを利用し、
各端末への配信を行っています。
そのため、APNsからDevice Tokenを取得したあとで、
データストアに配信端末情報として登録する必要があります。
AppDelegateファイル内のapplication:didFinishLaunchingWithOptionsメソッド内で
Device Tokenの要求をAPNsに対して行います。
・サンプルコード
Frameworkのimportが必要となります。
import UserNotifications
///////////////////////////途中省略///////////////////////////////
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { (granted, error) in
if((error) != nil) {
return
}
if granted {
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
}
}
Device Tokenが取得できた場合は、同じAppDelegate.swiftの
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;
}
})
}
以上でアプリ側での設定は完了です。
アプリを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 = "プッシュ通知です"
// iOS端末を送信対象に設定する
push.isSendToIOS = true
// 即時配信を設定する
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"
// android端末を送信対象に設定する
push.isSendToAndroid = true
// 即時配信を設定する
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 = "プッシュ通知です"
// iOS端末を送信対象に設定する
push.isSendToIOS = true
// android端末を送信対象に設定する
push.isSendToAndroid = true
// 配信時刻を設定する
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テンプレートの保存が可能です。
- 配信日時、配信期限、パーミッションの内容は、テンプレートとして保存されません。
配信エラーとなった場合
プッシュ通知一覧の画面で、配信状況が配信エラーになる場合がございます。
エラーが発生する場合の主な理由と対策は、以下の通りです。
- iOS証明書の不具合
- iOS証明書を再設定し、端末情報を再度登録したうえで、プッシュ通知をテストしてください。
- iOS証明書の有効期限が切れている場合は、証明書を更新してください。※iOS証明書の有効期限切れについては、こちらもご参考ください。
- iOS証明書またはAndroidプッシュ通知設定ファイルを設定していないのに、両方のOSを対象にしてプッシュ通知を登録
- 配信対象はデフォルトでiOS/Androidの両方なので、iOS証明書とAndroidプッシュ通知設定ファイルをどちらも設定していないとエラーになります。
配信エラーとなった場合に、管理画面からmobile backend側のログについて
確認することはできませんので、ご不明な点がございましたらお気軽にお問い合わせください。
ダミーデータを登録した端末を指定してプッシュ通知を行わない
プッシュ通知を配信する端末の中に、
テスト目的などでダミーデータを入力した端末が含まれていると、
他の端末も含めてプッシュ通知が配信されない場合がございます。
アプリ側でプッシュ通知が受信されるかを確認する場合は、
ダミーデータを含んだ端末を配信対象に含めないでください。
プッシュ通知でJSONデータを取得する
プッシュ通知にはJSON形式で任意のデータを含めることができるので、
通知を受信した時に、そのデータを受け取って処理を行うことができます。
アプリの状態によって、プッシュ通知を受信したときのメソッドが異なっており、
ペイロードを取得するためのキーも名前が違ってきます。
※注意
iOS 13.6以降で確認した場合、アプリがバックグラウンドにいる状態、ペイロードを取得するために、配信を登録する際、content-availableをtrue指定する必要があります。
なお、アプリはフォアグラウンドにいる場合、content-availableがfalseでも取得可能となっています。
アプリが起動されたときにプッシュ通知の情報(ペイロード)からデータを取得する
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
let payload:NSDictionary = launchOptions?[.init(rawValue: "UIApplicationLaunchOptionsRemoteNotificationKey")] as! NSDictionary
if let data = payload.object(forKey: "name") as? NSDictionary {
print("Data: \(data)")
}
return true
}
アプリが起動中のときにプッシュ通知を受信した場合
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
if let data = userInfo["name"] as? NSDictionary {
print("Data: \(data)")
}
}
ペイロードの内容について
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以上