質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

1回答

2053閲覧

Swift アプリ未起動時のプッシュ通知でのデータ更新方法の考え方

yamayuu8

総合スコア10

Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

1グッド

0クリップ

投稿2019/02/09 02:47

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

ymanya👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

アプリ未起動時にサーバーと通信をしていないと実現できない結果だと感じました。

これは、アプリ未起動時にサーバーと通信しているのでなく、
3.のプッシュ通知でメッセージを受信していて、
5.でLINEを開いた時に、3.でプッシュ通知された
メッセージ内容を読み込んでいると考えるのが自然ではないでしょうか?
プッシュ通知は約4Kバイトまでのメッセージを送信できます。

試しに、単純なメッセージではなく、画像を送信したところ、
機内モードを解除するまで画像は表示されませんでした。

投稿2019/02/12 02:41

TakeOne

総合スコア6299

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yamayuu8

2019/02/13 09:40

はい。自分もそう思います。ネットワークにつながっていない状態で最新の情報がとられるということは、既にpayload(と言う言い方で正しい?)でデータを渡しているのだろうと思ったのですが、だとすると、アプリ未起動状態でプッシュ通知を受けた時に、アプリを起動し登録処理が実行されないと実現できません。そうなると未起動状態ではプッシュ通知でアプリが起動しない。という情報と反対の内容になるため堂々巡りになってしまっています。 ただ、その後色々調べているとVoIPプッシュ通知だとアプリ未起動でもアプリを起動できるという記事がありましたので、どうもそちらではないか?と調査してみているところです。
TakeOne

2019/02/13 12:01 編集

説明が足りなかったかもしれませんが、受信済みのプッシュ通知一覧(自アプリ宛で未タップのもの)をアプリで取得する方法は知っていますか? それを使えば4.で機内モードにした後、5.でLINEを起動したタイミングで、未タップのプッシュ通知(の中に入っているメッセージ)を全て取得して、それをLINE内に表示できると思います。プッシュ通知を受信したタイミングでこっそりLINEを起動する必要はないと思います。 (参考) https://dev.classmethod.jp/smartphone/iphone/wwdc-2016-user-notifications-time-local-5/
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問