首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >没有显示在iOS设备上的Firebase消息通知(前景和背景)

没有显示在iOS设备上的Firebase消息通知(前景和背景)
EN

Stack Overflow用户
提问于 2020-01-09 01:36:14
回答 2查看 2.7K关注 0票数 3

我使用FCM为我的iOS应用程序创建和发送推送通知。

开发环境:

  • Xcode 11.3
  • iPhone X运行iOS 13.3
  • Swift 5.2

Pod版本:

6.14.0

  • FirebaseMessaging 4.1.10

  • FirebaseInstanceID 4.2.8
  • Firebase

问题:

在遇到问题之前,我已经设置了我的应用程序,以便能够在应用程序同时处于后台和前台时接收通知。我对自己很满意,我提交了密码。在此之后,我无法在前台或后台接收通知。无论使用的通知是从云消息传递仪表板还是邮递员发送的,我都收到了成功的响应,但通知从未出现。

起初,我想我可能已经达到了通知配额,但现在是2天后的事实。

来排除我尝试过的故障:

卸载和重新安装该应用程序(刷新设备令牌) FirebaseApp.configure()

  • Downloaded之前,

  • UIApplication.shared.registerForRemoteNotifications()移动到一个新的GoogleService-Info.plist,并替换了绑定id's等所有match

  • Updated防火墙的existing

  • Checked,最新的(FirebaseMessaging为4.1.9,如果有帮助的话)

  • Set Messaging.messaging().shouldEstablishDirectChannel = true

  • Removed,并将所需的capabilities

  • Set FirebaseAppDelegateProxyEnabled重新添加到YES和NO

h 145Set shouldEstablishDirectChannel = true

  • Set从useMessagingDelegateForDirectChannel = true

  • Moved ()到applicationDidBecomeActive()

的一些逻辑

代码:

注意:这是最初为我工作的未修改的代码。

AppDelegate.swift

代码语言:javascript
运行
复制
import UIKit
import Firebase
import FBSDKCoreKit
import GoogleMaps
import SwiftLocation
import GooglePlaces
import Crashlytics
import GoogleSignIn
import Armchair
import UserNotifications
import FirebaseMessaging

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {

    var window: UIWindow?
    var swipeNavigationViewController: SwipeNavigationViewController!

    override init() {
        super.init()

        FirebaseApp.configure()

        Database.database().isPersistenceEnabled = true
        swipeNavigationViewController = SwipeNavigationViewController()
    }

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool  {
        FirebaseConfiguration.shared.setLoggerLevel(.error)
        ApplicationDelegate.shared.application(application, didFinishLaunchingWithOptions: launchOptions)

        // Google Maps
        GMSServices.provideAPIKey(FireBaseConstants.GoogleAPIKey)
        GMSPlacesClient.provideAPIKey(FireBaseConstants.GoogleAPIKey)
        GeocoderRequest.GoogleOptions(APIKey: FireBaseConstants.GoogleAPIKey)

        let navigationViewController = UINavigationController(rootViewController: swipeNavigationViewController)
        navigationViewController.setNavigationBarHidden(true, animated: false)

        self.window?.rootViewController = navigationViewController
        self.window?.makeKeyAndVisible()

        showAlertIfPointedTowardProductionDatabase()
        setupReviewRequest()

        UIApplication.shared.registerForRemoteNotifications()

        let center = UNUserNotificationCenter.current()
        center.requestAuthorization(options:[.badge, .alert, .sound]) { (granted, error) in
            // If granted comes true you can enabled features based on authorization.
            guard granted else { return }
            DispatchQueue.main.async {
                print("UserID: \(UserManager.sharedManager.currentUser?.userID)")
                let pushManager = PushNotificationManager(userID: "currently_logged_in_user_id")
                pushManager.registerForPushNotifications()
            }
        }

        UNUserNotificationCenter.current().delegate = self

        return true
    }

    func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        let handledByFB = ApplicationDelegate.shared.application(app, open: url, options: options)

        var handledByGoogle = false
        if !handledByFB {
            handledByGoogle = GIDSignIn.sharedInstance().handle(url)
        }

        let handled = handledByFB || handledByGoogle

        return handled
    }

    private func setupReviewRequest() {
        //Code...
    }

    // This method will be called when app received push notifications in foreground
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        completionHandler([.alert, .badge, .sound])
    }
}

PushNotificationManager.swift

代码语言:javascript
运行
复制
import Foundation
import Firebase
import FirebaseFirestore
import FirebaseMessaging
import UIKit
import UserNotifications

class PushNotificationManager: NSObject, MessagingDelegate, UNUserNotificationCenterDelegate {

    let userID: String
    let gcmMessageIDKey = "gcm.message_id"

    init(userID: String) {
        self.userID = userID
        super.init()
    }

    func registerForPushNotifications() {
        let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]

        UNUserNotificationCenter.current().requestAuthorization(options: authOptions) { (_, error) in
            guard error == nil else{
                print(error!.localizedDescription)
                return
            }
        }

        //get application instance ID
        InstanceID.instanceID().instanceID { (result, error) in
            if let error = error {
                print("Error fetching remote instance ID: \(error)")
            } else if let result = result {
                print("Remote instance ID token: \(result.token)")
            }
        }

        UIApplication.shared.registerForRemoteNotifications()
        updateFirestorePushTokenIfNeeded()
    }

    func updateFirestorePushTokenIfNeeded() {
        if let token = Messaging.messaging().fcmToken {
            //            let usersRef = Firestore.firestore().collection("users_table").document(userID)
            //            usersRef.setData(["fcmToken": token], merge: true)
            print("Remote instance ID token: \(token)")
        }
    }

    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
        print("Firebase registration token: \(fcmToken)")

        let dataDict:[String: String] = ["token": fcmToken]
        NotificationCenter.default.post(name: Notification.Name("FCMToken"), object: nil, userInfo: dataDict)
        // TODO: If necessary send token to application server.
        // Note: This callback is fired at each app startup and whenever a new token is generated.
    }

    func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) {
        print("Received data message: \(remoteMessage.appData)")
    }

    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        print(response)
    }

    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
        if let messageID = userInfo[gcmMessageIDKey] {
            print("Message ID: \(messageID)")
        }

        print(userInfo)
    }

    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        print("Unable to register for remote notifications: \(error.localizedDescription)")
    }

    func application(_ application: UIApplication,didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        let tokenParts = deviceToken.map { //data -> String in
            return String(format: "%02.2hhx", $0)
        }

        Messaging.messaging().apnsToken = deviceToken
        Messaging.messaging().setAPNSToken(deviceToken, type: .unknown)
        UserDefaults.standard.synchronize()
    }
}

--这是使用以下所有链接设置的(我肯定还有几个其他链接也忘了):

响应信息:

邮差:

代码语言:javascript
运行
复制
{
    "multicast_id": 2586780331808083728,
    "success": 1,
    "failure": 0,
    "canonical_ids": 0,
    "results": [
        {
            "message_id": "0:1578532253832479%2b1845e62b1845e6"
        }
    ]
}

云消息传递:

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-01-09 20:34:43

我能够通过搬家来解决这个问题

代码语言:javascript
运行
复制
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)

从PushNotificationManager到AppDelegate。希望这能帮到别人!

票数 2
EN

Stack Overflow用户

发布于 2021-07-06 20:27:45

您可以在控制器层中使用didRegisterForRemoteNotifications。我的控制器中有一个私有方法,它也调用registerForRemoteNotifications。我在AppDelegate中实例化了我的控制器,因此它可以立即使用,而且当我试图在没有强引用的情况下使控制器生效时,我确实遇到了问题,这可能与弱委托有关。

这是我的整个appDelegate

代码语言:javascript
运行
复制
import UIKit
import Firebase

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    var controller: FirebaseMessagingController!
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        FirebaseApp.configure()
        
        self.controller = FirebaseMessagingController.shared
        return true
    }

    // MARK: UISceneSession Lifecycle

    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.
    }


}

我的控制器是这样的:

代码语言:javascript
运行
复制
    private init() {
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(receiveToken(_:)),
            name: .tokenKey,
            object: nil)
        
        registerForRemoteNotifications(UIApplication.shared)
        requestNotificationPermissions { _ in } // TODO: move to more user friendly place
        Messaging.messaging().delegate = UIApplication.shared.delegate as? MessagingDelegate
        UNUserNotificationCenter.current().delegate = UIApplication.shared.delegate as? AppDelegate
    }
    
    @objc private func receiveToken(_ notification: Notification) {
        
        guard let tokenDict = notification.userInfo as? [Notification.Name: String],
              let token = tokenDict[.tokenKey] else { return }
        self.token = token
        let apiTokenDict = ["token": token]
        if AuthService.shared.isLoggedIn {
            guard let user = AuthService.shared.user else { return }
            FirebaseDatabaseController().updateValues(for: APIRef.userRef(userId: user.userId).endpoint, with: apiTokenDict)
        }
        
    }
    
    private func registerForRemoteNotifications(_ application: UIApplication) {
        application.registerForRemoteNotifications()
    }
    
    private func requestNotificationPermissions(completion: @escaping (Result<Bool, Error>) -> Void) {
        
        let authOptions: UNAuthorizationOptions = [.alert, .badge]
        UNUserNotificationCenter.current().requestAuthorization(
            options: authOptions,
            completionHandler: { success, error in
                if success {
                    completion(.success(success))
                } else if let error = error {
                    completion(.failure(error))
                } else {
                    let error = NSError(domain: #function, code: 0)
                    completion(.failure(error))
                }
            }
        )
        
    }

didRegisterForRemoteNotifications也在我的控制器中,并接收令牌:

代码语言:javascript
运行
复制
    // set FirebaseMessaging service with apnsToken
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        Messaging.messaging().apnsToken = deviceToken
    }

编辑:实际上,我在AppDelegate中还有一个接收注册令牌的部分,但是将它隐藏在控制器中的一个扩展中:

代码语言:javascript
运行
复制
extension AppDelegate: MessagingDelegate {
    
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
        guard let fcmToken = fcmToken else { return }
        let dataDict:[NSNotification.Name: String] = [.tokenKey: fcmToken]
        NotificationCenter.default.post(name: .tokenKey, object: nil, userInfo: dataDict)
    }
    
}

考虑到这一点,这是一个奇怪的选择,因为我可能会让控制器成为消息传递委托,并在那里完成它而不发布通知.

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59656069

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档