LINEなどのメッセージアプリのようにプッシュ通知受信時にデータ更新(バッヂ、ユーザーデフォルト等)したい
Swiftでアプリを作成しています。まだ部品ごとのテスト段階ですが、プッシュ通知を実装するためFirebaseを利用し、functions & node.jsでデータの監視を行い、データが追加された段階でプッシュ通知を送信しています。テスト環境は2台の実機を使い、1台でアプリ内のボタンを押すと上記機能が実行され、もう1台の実機に通知が飛びます。
アプリ未起動時の通知受信時のコード実行ができない。
プッシュ通知受信の確認は以下でできています。
確認方法はAppDelegate内でユーザーデフォルトに値を入れるコードが実行されているか?で確認をとっています。(OKという表現にします)
アプリ起動時
1.通常のプッシュ通知
1−1.フォアグランド OK
1−2.バックグランド OK
2.サイレント通知
2−1.フォアグランド OK
2−2.バックグランド OK
アプリ未起動
3.通常のプッシュ通知 NG(ただし、通知自体は表示される)
4.サイレント通知 NG
(プッシュ通知側の設定でバッジの値を更新できることも確認できています)
このアプリ未起動時にユーザーデフォルトの更新などをしたいと考えています。
調査したこと
インターネット上で日本語・英語サイトを調査し、下記のような情報を目にしました。
・サイレント通知でデータ更新した後ローカル通知を実行する方法がある
・プッシュ通知は届く保証がない
・アプリ未起動時にはプッシュ通知でアプリが起動することはない
・バッチはサーバー上で管理し、プッシュ通知でセットするしかない
など
テスト結果とこれらの情報から、アプリが起動されている間にサーバーと何かしらのトリガーで同期をとり、サーバーに保存したバッヂ(数値)をプッシュ通知のapnsオプションで送ることが正解だと考えました。
考え方の裏づけ調査とその結果
この考えを裏づけるために、LINEで下記実験をしました。
1.LINEを未起動にする
2.別スマホでLINEを送る
3.LINEにプッシュ通知が届く(バッヂ更新)
4.機内モードにしてネットワークと回線を遮断する
5.LINEを開く
6.別スマホでLINEでもう1通を送る
7.機内モードを解除して通知を受信する(バッヂ更新)
予想していたのは、
5.LINEを開いてもメッセージはまだない。
機内モードでバッチをゼロにしているので、次の通知でうけるバッチが間違う。と思っていたのですが、現実としては、5.でメッセージが表示され(既にメッセージ受信済み)7.でのバッチ数もきちんとローカル側の値を更新した数値でした。
アプリとしては当然あるべき姿だとは思いますが、
これで私の仮説は間違っていたということがわかりました。
アプリ未起動時にサーバーと通信をしていないと実現できない結果だと感じました。
これ以降、未起動時のプッシュ通知でのコード実行ができないという問題から抜け出せません。
プッシュ通知の方法を見直しをすべきか、Xcodeの設定が違うのか、そもそも考え方が違うのか、アドバイスを頂きたく、よろしくお願いいたします。
node
1 2const pushMSG = (fcmToken) => ({ 3 notification: { 4 title: "タイトル", 5 body: "内容", 6 }, 7 apns: { 8 headers: { 9 "apns-priority": "10" 10 }, 11 payload: { 12 aps: { 13 sound: "default", 14 contentAvailable: 1, 15 } 16 } 17 }, 18 data: { msg: "メッセージ" }, 19 token: fcmToken, 20}); 21 22 23const SilentPush = (fcmToken) => ({ 24 apns: { 25 headers: { 26 "apns-priority": "10" 27 }, 28 payload: { 29 aps: { 30 contentAvailable: 1, 31 } 32 } 33 }, 34 data: { msg: "メッセージ" }, 35 token: fcmToken, 36}); 37 38...省略 39 40admin.messaging().send(SilentPush(fcmToken)) 41.then((response) => { 42 console.log('Successfully:', response) 43}) 44.catch((e) => { 45 console.log('Error:', e) 46}) 47admin.messaging().send(pushMSG(fcmToken)) 48.then((response) => { 49 console.log('Successfully:', response) 50}) 51.catch((e) => { 52 console.log('Error:', e) 53}) 54
Swift AppDelegate.swiftの抜粋です。
アプリの通知承認設定は実施済みです。
Firebaseのfcmトークン系も通知はできているのでOKだと考えています。
混乱しているため、当てずっぽう作戦のコードという状況です。
swift
1 2class AppDelegate: UIResponder, UIApplicationDelegate, MessagingDelegate, UNUserNotificationCenterDelegate{ 3 4func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 5 6application.unregisterForRemoteNotifications() 7application.registerForRemoteNotifications() 8 9application.setMinimumBackgroundFetchInterval(UIApplication.backgroundFetchIntervalMinimum) 10 11---ユーザーデフォルトに書き込み--- 12 13return true 14} 15 16 17 18 19func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { 20 21---ユーザーデフォルトに書き込み--- 22 23completionHandler(.newData) 24} 25 26 27func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { 28 29---ユーザーデフォルトに書き込み--- 30 31completionHandler(.newData) 32} 33 34 35func userNotificationCenter(_ center: UNUserNotificationCenter,didReceive response: UNNotificationResponse,withCompletionHandler completionHandler: @escaping () -> Void) { 36 37---ユーザーデフォルトに書き込み--- 38 39}
補足情報(FW/ツールのバージョンなど)
Swift4 Firebase Firestone Functions node.js
Xcode 10.0
Capabilities-Background-mode=ON 、Background Fetchチェック、Remote Notificationチェック
Push Notification=ON
iOS 11
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/02/13 09:40
2019/02/13 12:01 編集