This is really strange. I tested the firebase notification from my Xcode and works fine. Basically I created a new user in Xcode using the simulator and used my phone to create another one. I received a notification on my phone. However, after I published my app and tried between phones, it did not work.
Here is my code in AppDelegate:
import UIKit
import Firebase
import FirebaseMessaging
import UserNotifications
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, MessagingDelegate, UNUserNotificationCenterDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
FirebaseApp.configure()
// Messaging Delegate
Messaging.messaging().delegate = self
// Notification delegate
UNUserNotificationCenter.current().delegate = self
if #available(iOS 10.0, *) {
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in })
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
return true
}
// fcm Token
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
print("Registered with FCM with token:", fcmToken)
// let newVC = LoginViewController()
// let token: [String:AnyObject] = [Messaging.messaging().fcmToken!:Messaging.messaging().fcmToken as AnyObject]
// newVC.postToken(Token: token)
}
// Listen for user notifications - basically show the notification while a user is on foreground mode
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler(.alert)
// Reset badge number to zero
if let userID = Auth.auth().currentUser?.uid {
let dbRef = Database.database().reference()
dbRef.child("Users Info").child(userID).updateChildValues(["badge":"0"], withCompletionBlock: { (err, ref) in
if err != nil {
print(err!)
return
}
})
}
// if let badgeNumber = notification.request.content.badge {
//
// if let mainTabBarController = window?.rootViewController as? MainTabBarControllerViewController {
//
// mainTabBarController.tabBar.items?[1].badgeValue = String(Int(badgeNumber))
//
//
// }
// }
// let badgeNumberServer = Int(notification.request.content.badge!)
//
// // Increment badge number
// badgeNumber = badgeNumber + badgeNumberServer
// print(badgeNumber)
//// app.applicationIconBadgeNumber = badgeNumber
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
// How do we access our MainTabBarController from AppDelegate
if let mainTabBarController = window?.rootViewController as? MainTabBarControllerViewController {
// transition to the second tab
mainTabBarController.selectedIndex = 1
mainTabBarController.tabBar.items?[1].badgeValue = nil
}
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
completionHandler(.newData)
if let aps = userInfo["aps"] as? [String:Any] {
let badgeNumber = aps["badge"] as! Int
if let mainTabBarController = window?.rootViewController as? MainTabBarControllerViewController {
mainTabBarController.tabBar.items?[1].badgeValue = String(Int(badgeNumber))
}
}
}
// func loadUserInfo() {
// let userID = Auth.auth().currentUser?.uid
//
// if let actualUserID = userID {
//
// Database.database().reference().child("Users Info").child(actualUserID).observe(.childAdded, with: { (snapshot) in
//
// if let dictinaryProperty = snapshot.value as? [String: AnyObject]{
//
// let userInformantion = UserInfo()
//
// userInformantion.setValuesForKeys(dictinaryProperty)
//
//// print(userInformantion.requestsBadge)
//
//
// }
// let value = snapshot.value as? NSDictionary
//
// let rBadge = value?["requestsBadge"] as? String ?? ""
//
// // Count the number of requestsBadge
// let reqBadge = Int(rBadge)! + badge
// Upload into Firebase
// self.uploadUserInfo(Badge:reqBadge)
//
// }, withCancel: nil)
//
// }
// }
// func uploadUserInfo(Badge:Int) {
//
// let userID = Auth.auth().currentUser?.uid
//
// if let actualUserID = userID {
//
// Database.database().reference().child("Users Info").child(actualUserID).updateChildValues(["requestsBadge":String(Badge)], withCompletionBlock: { (err, ref) in
// if err != nil {
// print(err!)
// return
// }
// })
//
// }
//
// }
func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
// application.applicationIconBadgeNumber = badgeNumber
}
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
// print(application.applicationIconBadgeNumber)
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
// Reset tab bar's badge if the user lefts the app on Requests tab and come back to it
if let mainTabBarController = window?.rootViewController as? MainTabBarControllerViewController {
if mainTabBarController.selectedIndex == 1 {
// Reset Requests tab's badge
mainTabBarController.tabBar.items?[1].badgeValue = nil
}
}
// print(application.applicationIconBadgeNumber)
// Rest the app badge
application.applicationIconBadgeNumber = 0
// Reset badge number to zero
if let userID = Auth.auth().currentUser?.uid {
let dbRef = Database.database().reference()
dbRef.child("Users Info").child(userID).updateChildValues(["badge":"0"], withCompletionBlock: { (err, ref) in
if err != nil {
print(err!)
return
}
})
}
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
}
and here is Node.JS
//// A New Request
// Send Push notification using FCM token manually
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendPushNotification = functions.database.ref('Received Downs/{owner}/{propID}')
.onCreate(event => {
// get the owner name and propID
var owner = event.params.owner;
var propID = event.params.propID;
// Log it
console.log('Owner: ' + owner + ' Property ID: ' + propID);
// Get the list of device notification tokens.
// return admin.database().ref(`/Users Info/${owner}`).once('value', snapshot => {
//
// var ownerID = snapshot.val();
// Multiple tokens
// const getDeviceTokensPromise = admin.database().ref(`/Users Info/${owner}/Tokens`).once('value');
//
// return Promise.all([getDeviceTokensPromise]).then(results => {
// const tokensSnapshot = results[0];
// This will find requester ID
return admin.database().ref(`/Received Downs/${owner}/${propID}`).once('value', snapshot => {
// First will find the property the requester downed
var property = snapshot.val();
// Find the requester's name
return admin.database().ref('/Users Info/' + property.downedBy).once('value', snapshot => {
// Requester's ID
var downedBy = snapshot.val();
return admin.database().ref('/Users Info/' + owner).once('value', snapshot => {
var ownerValue = snapshot.val();
var badgeNumber = parseInt(ownerValue.badge) + 1;
// Listing all tokens. (the function save the keys of given variable)
//ownerID.token
const tokens = ownerValue.Tokens;
// const tokens = Object.keys(tokensSnapshot.val());
// Notification details.
const payload = {
// to: 'tokens',
// priority: 'default',
notification: {
title: 'You have a new request!',
body: `A new request from ${downedBy.name}.`,
badge:`${badgeNumber}`,
sound: 'default',
content_available: "true",
}
};
// Send to all tokens of a device
admin.messaging().sendToDevice(tokens, payload)
.then(response => {
console.log("Successfully sent message:", response);
}).catch(function(error) {
console.log("Error sending message:", error);
});
// Upload the new badge number into firebase Realtime database
return admin.database().ref('/Users Info/' + owner).update({badge:badgeNumber});
})
})
})
// })
})
Here is what I got on Firebase Function log
I truly have no idea what is the issue.