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

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

ただいまの
回答率

87.79%

Push通知が届かなくなった(ios, fcm)

受付中

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,898

score 0

AppStoreにアプリが公開されてからPush通知が届かなくなりました。(正確なタイミングは不明、リリースが原因かも不明)
本番環境だけでなく、開発環境でも届かなくなりました。
公開される2日前までは、開発環境での実機シミューレートやTestFlightでのテストで、問題なく通知は届いていました。
公開されたのは昨日です。昨日はプッシュ通知のテストはしていません。

状況

SwiftUIを使って開発しています。
GitHubリポジトリ

認証キー(p8)を使用しています。

FCMのコンソールから通知を作成してみましたが、届きませんでした。(テストの段階では届いていました)

調べていたところ下のような質問を発見しました。
FCMでiOSアプリにPush通知が来ない

 調べているうちに、「FireBaseの対応が追い付かず、リリース直後はCloudMessagingが動作しない事がある」との記述を見つけ、しばらく放置しました。先日、FireBaseから試験通知を行ったところ、無事アプリで受け取ることができました

上の記述は、他のページで発見することができませんでした。

試したこと

curlで通知を叩いて結果を調べてみる

curl -X POST --header "Authorization: key=<FCMのコンソールにあるサーバキー>" \
--Header "Content-Type: application/json" \
https://fcm.googleapis.com/fcm/send \
-d @- << EOF
{
    "to": "<通知をおくりたいFCM Token>",
    "notification": {
        "body": "お知らせテスト"
    },
    "priority":10,
    "mutable_content":true
}
EOF

# 結果
{"multicast_id":***********,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"**********"}]}

デバイストークンが誤っている、登録されていない場合はエラーレスポンスコードが返ってきます。
デバイストークンが登録されていない、サーバーキーが誤っている等の理由ではなさそうです。

公式リファレンス

AppDelegate

AppDelegateのコードを載せておきます。

import SwiftUI
import Firebase
import PartialSheet
import FirebaseMessaging
import UserNotifications
import GoogleMobileAds

@main
struct StudyLevel_App: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    let sheetManager: PartialSheetManager = PartialSheetManager()
    let levelUpViewModel = LevelUpViewModel()

    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(sheetManager)
                .environmentObject(levelUpViewModel)
        }
    }
}

class AppDelegate: UIResponder, UIApplicationDelegate, MessagingDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        FirebaseApp.configure()
        GADMobileAds.sharedInstance().start(completionHandler: nil)
        Messaging.messaging().delegate = self
        if #available(iOS 10.0, *) {
            let center = UNUserNotificationCenter.current()
            center.delegate = self

            let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
            center.requestAuthorization(options: authOptions) { granted, error in
                guard granted else { return }

                DispatchQueue.main.async {
                    application.registerForRemoteNotifications()
                }
            }
       } else {
           let settings: UIUserNotificationSettings =
               UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
           application.registerUserNotificationSettings(settings)
       }

        application.registerForRemoteNotifications()

        return true
    }

    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
        print("Firebase registration token: \(String(describing: fcmToken))")
        DeviceRegister().register(token: fcmToken)
    }

    func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
       // Called when a new scene session is being created.
       // Use this method to select a configuration to create the new scene with.
       return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
   }

   func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
       // Called when the user discards a scene session.
       // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
       // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
   }

   func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
       // Print message ID.
       if let messageID = userInfo["gcm.message_id"] {
           print("Message ID: \(messageID)")
       }

       // Print full message.
       print(userInfo)
   }

   func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                    fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
       // Print message ID.
       if let messageID = userInfo["gcm.message_id"] {
           print("Message ID: \(messageID)")
       }

       // Print full message.
       print(userInfo)

       completionHandler(UIBackgroundFetchResult.newData)
   }
}

@available(iOS 10, *)
extension AppDelegate : UNUserNotificationCenterDelegate {

   func userNotificationCenter(_ center: UNUserNotificationCenter,
                               willPresent notification: UNNotification,
                               withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
       let userInfo = notification.request.content.userInfo

       if let messageID = userInfo["gcm.message_id"] {
           print("Message ID: \(messageID)")
       }

        print(userInfo)

        completionHandler([.list, .banner, .sound, .badge])
   }

   func userNotificationCenter(_ center: UNUserNotificationCenter,
                               didReceive response: UNNotificationResponse,
                               withCompletionHandler completionHandler: @escaping () -> Void) {
       let userInfo = response.notification.request.content.userInfo
       if let messageID = userInfo["gcm.message_id"] {
           print("Message ID: \(messageID)")
       }

       print(userInfo)

       completionHandler()
   }
}

extension Color {
    static let backgroundGray = Color("backgroundGray")
}

xcodeのログ

StudyLevel_(12483,0x103e4b8c0) malloc: recording malloc and VM allocation stacks using lite mode
2021-01-04 20:46:46.322285+0900 StudyLevel_[12483:7352109] 7.3.0 - [Firebase/Analytics][I-ACS023007] Analytics v.7.3.0 started
2021-01-04 20:46:46.322600+0900 StudyLevel_[12483:7352109] 7.3.0 - [Firebase/Analytics][I-ACS023008] To enable debug logging set the following application argument: -FIRAnalyticsDebugEnabled (see http://goo.gl/RfcP7r)
2021-01-04 20:46:46.330274+0900 StudyLevel_[12483:7352113] 7.3.0 - [Firebase/Messaging][I-FCM001000] FIRMessaging Remote Notifications proxy enabled, will swizzle remote notification receiver handlers. If you'd prefer to manually integrate Firebase Messaging, add "FirebaseAppDelegateProxyEnabled" to your Info.plist, and set it to NO. Follow the instructions at:
https://firebase.google.com/docs/cloud-messaging/ios/client#method_swizzling_in_firebase_messaging
to ensure proper integration.
2021-01-04 20:46:46.654976+0900 StudyLevel_[12483:7352102] 7.3.0 - [Firebase/Analytics][I-ACS800023] No pending snapshot to activate. SDK name: app_measurement
2021-01-04 20:46:46.667848+0900 StudyLevel_[12483:7352109] 7.3.0 - [Firebase/Analytics][I-ACS023012] Analytics collection enabled
2021-01-04 20:46:46.668168+0900 StudyLevel_[12483:7352109] 7.3.0 - [Firebase/Analytics][I-ACS023220] Analytics screen reporting is enabled. Call +[FIRAnalytics logEventWithName:FIREventScreenView parameters:] to log a screen view event. To disable automatic screen reporting, set the flag FirebaseAutomaticScreenReportingEnabled to NO (boolean) in the Info.plist
2021-01-04 20:46:48.385282+0900 StudyLevel_[12483:7351951] <Google> To get test ads on this device, set: GADMobileAds.sharedInstance.requestConfiguration.testDeviceIdentifiers = @[ @"bae7a10619e47a268758cd60b2f2643e" ];
2021-01-04 20:46:48.387143+0900 StudyLevel_[12483:7352102] 7.3.0 - [Firebase/Analytics][I-ACS025026] Deferring to Firebase for event data collection
2021-01-04 20:46:49.797186+0900 StudyLevel_[12483:7351951] WF: === Starting WebFilter logging for process StudyLevel_
2021-01-04 20:46:49.797361+0900 StudyLevel_[12483:7351951] WF: _userSettingsForUser mobile: {
    filterBlacklist =     (
    );
    filterWhitelist =     (
    );
    restrictWeb = 1;
    useContentFilter = 0;
    useContentFilterOverrides = 0;
    whitelistEnabled = 0;
}
2021-01-04 20:46:49.797637+0900 StudyLevel_[12483:7351951] WF: _WebFilterIsActive returning: NO
2021-01-04 20:46:52.192272+0900 StudyLevel_[12483:7351951] [TraitCollection] Class CKBrowserSwitcherViewController overrides the -traitCollection getter, which is not supported. If you're trying to override traits, you must use the appropriate API.

バージョン

  • swift 5.3.1
  • Xcode 12.2
  • iOS 14.0

実機は、iOS14.2のiPhone11です。
他の端末も使用してテストしてみましたが、うまくいきませんでした。

補足

このあたりを調べると良い、この情報が欲しいなどのコメントがありましたらよろしくお願いします。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • nyantaroo

    2021/01/05 12:50

    Xcodeの実機デバックの際に、didReceiveRegistrationTokenが返すトークンを確認しているので、実機のトークンと一致していると思われます。
    Firebaseのコンソールで全体に向けて通知を送信してみましたが、それでもとどきませんでした。

    キャンセル

  • hoshi-takanori

    2021/01/05 20:51

    こちらは確認されましたか?
    https://qiita.com/shinkuFencer/items/4dc135a13cfd4cf4bbb4

    キャンセル

  • nyantaroo

    2021/01/05 21:23

    認証キーを用いてるので、開発環境と本番環境の区別はないはずです。
    ↓認証キーと証明書の比較記事
    https://takamii.hatenablog.com/entry/2020/07/13/190027

    ちなみに証明書を使用する方法も試してみましたが、うまくいきませんでした。

    キャンセル

回答 1

0

自分の体験談ですが,Build SettingのProduct Nameに日本語(utf-8文字列)が含まれており,本番での通知が届かないことがありました。こちら確認してみてください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2021/01/15 21:30

    貴重な情報ありがとうございます。
    確認したところ、ProductName には日本語は含まれていませんでしたが、アンダーバーが含まれていたので、削除してテストしてみましたがうまくいきませんでした。

    キャンセル

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

  • ただいまの回答率 87.79%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る