Я использую FCM для создания и отправки уведомлений pu sh для моего приложения iOS.
Среда разработки:
Версии Pod:
- Firebase 6.14.0
- FirebaseMessaging 4.1.10
- FirebaseInstanceID 4.2.8
Проблема:
Прежде чем столкнуться с проблемой, я настроил свое приложение так, чтобы оно могло получать уведомления, когда приложение находилось как в фоновом, так и на переднем плане. Очень довольный собой, я передал код. После этого момента я не смог получать уведомления на переднем плане или на заднем плане. Независимо от того, используется ли уведомление с панели мониторинга Cloud Messaging или POSTMAN, я получаю успешный ответ, но уведомление так и не появляется.
Сначала я подумал, что, возможно, достиг квоты уведомлений, но теперь через 2 дня факт.
Для устранения неполадок я попытался:
- Удалил и переустановил приложение (которое обновляет токен устройства)
- Перемещено
UIApplication.shared.registerForRemoteNotifications()
до FirebaseApp.configure()
- Загрузил бесплатный sh GoogleService-Info.plist и заменил существующий
- Проверено, что идентификаторы пакета et c все совпадают
- Обновлены модули Firebase до последней (FirebaseMessaging был на 4.1.9, если это помогает)
- Установить
Messaging.messaging().shouldEstablishDirectChannel = true
- Удалены и повторно добавлены необходимые возможности
- Установить
FirebaseAppDelegateProxyEnabled
на ДА и НЕТ - Установить
shouldEstablishDirectChannel = true
- Установить
useMessagingDelegateForDirectChannel = true
- Переместил некоторые логи c из didFinishLaunchingWithOptions () в applicationDidBecomeActive ()
Код:
Примечание: это неизмененный код, который изначально работал для меня.
AppDelegate.swift
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
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()
}
}
Это была установка используя все следующие ссылки (я уверен, что с несколькими другими я тоже забыл):
Ответная информация:
Почтальон:
{
"multicast_id": 2586780331808083728,
"success": 1,
"failure": 0,
"canonical_ids": 0,
"results": [
{
"message_id": "0:1578532253832479%2b1845e62b1845e6"
}
]
}
Облачные сообщения: