I followed all the steps below and added the appropriate imports and code in App Delegate. I also made sure I allowed Notifications to be accepted when I ran the app.
Following the steps below, why is it that I can't receive the Notifications after I send one from the Firebase Cloud Messaging Console ?
In my Developer account I went to Certificates, Identifiers & Profiles
Under Keys, I selected All and clicked the Add button (+) in the upper-right corner
Under Key Description, I entered a unique name for the signing key
Under Key Services, I selected the APNs checkbox, then clicked Continue then clicked Confirm
I copied the Key ID (used in step 7) and clicked Download to generate and download the .p8 key
I went to Firebase, clicked the Gear Icon > Project Settings > Cloud Messaging (not Grow > Cloud Messaging like step 10)
Under iOS app configuration > APNs Authentication Key I went to the first section APNs Authentication Key (NOT APNs Certificates), selected Upload and uploaded the .p8 key, the Key ID, and my Team Id. The teamId is located in the Membership section and the keyId is the xxxxxxx part of the xxxxxxx.p8 file.
In my Xcode project I went to Capabilities > Background Modes, turned it On, and checked Remote Notifications
Then I went to > Push Notifications and turned it On which automatically generated an Entitlement Certificate for the app (it's inside the project navigator)
To send a notification in Firebase I went to Grow > Cloud Messaging > Send Your First Message > 1. Notification Text entered some random String > 2. Target and selected my app's bundleId > 3. Scheduling Now > 4. pressed Next > 5. selected sound and a badge > Review
In AppDelegate I added import UserNotifications, import FirebaseMessaging, import Firebase, registered for the UNUserNotificationCenterDelegate and added the code below.
To set up the reCAPTCHA verification I went to the Blue Project Icon > Info > URL Types then in the URL Schemes section (press the plus sign + if nothing is there), I entered in the REVERSED_CLIENT_ID from my GoogleService-Info.plist
I've added break points to all the print statements below and after I send a message from Firebase none of them get hit.
import UserNotifications
import FirebaseMessaging
import Firebase
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
UNUserNotificationCenter.current().delegate = self
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().requestAuthorization(options: [.sound,.alert,.badge]) {
[weak self] (granted, error) in
if let error = error {
print(error.localizedDescription)
return
}
print("Success")
}
application.registerForRemoteNotifications()
} else {
let notificationTypes: UIUserNotificationType = [.alert, .sound, .badge]
let notificationSettings = UIUserNotificationSettings(types: notificationTypes, categories: nil)
application.registerForRemoteNotifications()
application.registerUserNotificationSettings(notificationSettings)
}
}
// MARK:- UNUserNotificationCenter Delegates
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Messaging.messaging().setAPNSToken(deviceToken, type: MessagingAPNSTokenType.unknown)
var token = ""
for i in 0..<deviceToken.count{
token = token + String(format: "%02.2hhx", arguments: [deviceToken[i]])
}
print("Registration Succeded! Token: \(token)")
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("Notifcation Registration Failed: \(error.localizedDescription)")
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
if let gcm_message_id = userInfo["gcm_message_id"]{
print("MessageID: \(gcm_message_id)")
}
print(userInfo)
}
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler(.alert)
print("Handle push from foreground \(notification.request.content.userInfo)")
let dict = notification.request.content.userInfo["aps"] as! NSDictionary
let d = dict["alert"] as! [String:Any]
let title = d["title"] as! String
let body = d["body"] as! String
print("Title:\(title) + Body:\(body)")
showFirebaseNotificationAlertFromAppDelegate(title: title, message: body, window: self.window!)
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
print("\(response.notification.request.content.userInfo)")
if response.actionIdentifier == "yes"{
print("True")
}else{
print("False")
}
}
func showFirebaseNotificationAlertFromAppDelegate(title: String, message: String, window: UIWindow){
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
let action = UIAlertAction(title: "OK", style: .default, handler: nil)
alert.addAction(action)
window.rootViewController?.present(alert, animated: true, completion: nil)
}
}
The message gets sent successfully as you can see in the below pic but I never receive it.
I think you should also add this to your code otherwise you won't be receiving the push notifications. Firebase needs to now what the apns token is to send you the pushes.
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Messaging.messaging().apnsToken = deviceToken
}
seems like you are missing some of the configuration for the FCM to work properly.
From what I see you aren't sending the token to firebase and you aren't registering for the FCM.
See the documentation here https://firebase.google.com/docs/cloud-messaging/ios/client for more details.
To send the push message through the firebase you need to have the FCM token. The token you are using is the one coming from the APNS servers and you need to forward it to firebase.
I got the answer from here
I was supposed to add Messaging.messaging().delegate = self BEFORE FirebaseApp.configure()
I also had to add in the Messaging Delegate to receive the FCM Registration Token.
Inside didFinishLaunching add Messaging.messaging().delegate = self
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
Messaging.messaging().delegate = self // make sure this is added BEFORE FirebaseApp.Configure
FirebaseApp.configure()
// all the other code inside didFinishLaunching goes here...
}
// all the other methods from above goes here...
****Also at the bottom of the AppDelegate file add the Messaging Delegate and it's method. This is where the FCM Token is received:
extension AppDelegate : MessagingDelegate {
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
print("Your Firebase FCM Registration Token: \(fcmToken)")
}
}
Related
I have an iOS app that should be prepared to receive and show Cloud Messaging Notifications.
This is my AppDelegate class code:
import UIKit
import GooglePlaces
import Braintree
import Firebase
import Messages
import IQKeyboardManagerSwift
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
let gcmMessageIDKey = "gmc.message_id"
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
IQKeyboardManager.shared.enable = true
GMSPlacesClient.provideAPIKey("..")
BTAppSwitch.setReturnURLScheme("...")
FirebaseApp.configure()
if #available(iOS 10.0, *) {
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self
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()
Messaging.messaging().delegate = self
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.
}
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
if url.scheme?.localizedCaseInsensitiveCompare("faro.red.Jogua.payments") == .orderedSame {
return BTAppSwitch.handleOpen(url, options: options)
}
return false
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
// If you are receiving a notification message while your app is in the background,
// this callback will not be fired till the user taps on the notification launching the application.
// TODO: Handle data of notification
// With swizzling disabled you must let Messaging know about the message, for Analytics
// Messaging.messaging().appDidReceiveMessage(userInfo)
// Print message ID.
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
// Print full message.
print(userInfo)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
// If you are receiving a notification message while your app is in the background,
// this callback will not be fired till the user taps on the notification launching the application.
// TODO: Handle data of notification
// With swizzling disabled you must let Messaging know about the message, for Analytics
// Messaging.messaging().appDidReceiveMessage(userInfo)
// Print message ID.
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
// Print full message.
print(userInfo)
completionHandler(UIBackgroundFetchResult.newData)
}
}
#available(iOS 10, *)
extension AppDelegate : UNUserNotificationCenterDelegate {
// Receive displayed notifications for iOS 10 devices.
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
let userInfo = notification.request.content.userInfo
// With swizzling disabled you must let Messaging know about the message, for Analytics
// Messaging.messaging().appDidReceiveMessage(userInfo)
// Print message ID.
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
// Print full message.
print(userInfo)
// Change this to your preferred presentation option
completionHandler([[.alert, .sound, .badge]])
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
// Print message ID.
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
// Print full message.
print(userInfo)
completionHandler()
}
}
extension AppDelegate: MessagingDelegate {
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.
}
}
I am getting the Firebase Registration Token, as shown in the debugger:
Firebase registration token: dPyG4q2scEFQhsObtyfdUx:APA91bE9O5MmMiJ2f7...
But after sending a notification from Firebase Console, I don't get it in my real device.
What am I doing wrong?
I think I have figured it out .. it is related to the expiry of a provisioning profile or at least it was in my case..
in xcode, open your project, then go to the blue APP_NAME in the top left of your project navigator, then choose the correct TARGET in the inner new left hand nav that appeared. it will show you a very white config screen with a hard to recognise series of "tabs" (blue text going blue on select) named:
General / Signing & Capabilities / Resource Tags / Info / Build Settings / Build Phases
choose Signing & Capabilities
the select "all" in the second set of rather hard to detect tabs (an inner list of small black words on white background, blue text for selected names named: "All" "Debug" "Release" you want "ALL")
the untick "automatically manage signing" under "Signing" (a rather hard to detect twister) it should then (INCREDIBLY in my mind) "awake" to discover "an issue" a red message that something is not right (mine did), it was an "expiry" on the "push certificate" which I am fairly sure did not exist last time I did this) I just re-selected all the defaults then you can click "some button" (I forget the name but the button appears there and then mid page, next to the red, and if you click it it spins itself away) and voila apple automatically updated it. Once the red goes away, then you can reclick "automatically manage signing" and the error was gone for me
BEAR IN MIND BEFORE I DID THIS I did in fact ensure I had created 2 push notification certificates using Appliances\Keychain on my macbook then, saving to local drive, uploading them to https://developer.apple.com/membercenter/index.action following this click train:
"iOS, tvOS, watchOS" if you need to
Certificates, Identifiers and Profiles.
Pick "Identifiers" in list
chose your project
scroll to PUSH NOTIFICATIONS near bottom
click configure (or create) I think it's the only button anyway, mine now says "edit"
Create "Development SSL Certificate" and "Production SSL Certificate" (I did both)
upload the certificate you made with Appliances\Keychain
I am not sure if this will help you but it fixed it for me
oh one more thing to bear in mind
make sure you go to https://console.firebase.google.com/ and follow this click train:
"Your Firebase projects"
(choose yours)
(very top left) "Project Overview" (cog) "Project Settings"
(choose) "Cloud Messaging" tab
(scroll down to) "iOS app configuration"
under "APNs Certificates" make sure your APN certificates are not expired
Last night I was testing Push Notifications from Firebase in my iOS app, and it was working as expected
I was able to send a notification from at Cloud Function to a specific FCM token.
This morning notification doesn't arrive when using the same method.
Cloud Function
Here's the function that I use to send the notification:
function sendNotification(title: string, body: string, token: string): Promise<void> {
const message: admin.messaging.Message = {
apns: {
headers: {
'apns-priority': '10'
},
payload: {
aps: {
alert: {
title: title,
body: body,
},
sound: "default"
}
}
},
token: token
}
return admin.messaging().send(message).then(response => { console.log(`Notification response ${response}`) }).then(justVoid)
}
Here token is the token I received from the InstanceId in the iOS app.
When this function is triggered, I see the following in Firebase web console's Cloud Function log:
Notification response projects/project-name/messages/0:1571998931167276%0f7d46fcf9fd7ecd
Which, as far as I understand, is a success message. So I'm expecting the notification to show up on the device at this point, but nothing.
iOS App
I've followed this guide to troubleshoot, and am sure that the setup is right: https://firebase.google.com/docs/cloud-messaging/ios/first-message?authuser=0
I did try to re-install the app on the device on which Im testing: I've verified that the app does through these step after re-install:
call: UNUserNotificationCenter.current().requestAuthorization(options:, completionHandler:)
call: UIApplication.shared.registerForRemoteNotifications()
listen to updated FCM token by implementing: func messaging(_ messaging:, didReceiveRegistrationToken fcmToken:)
call: InstanceID.instanceID().instanceID(handler:)
double check that notifications is allowed for my application in the iOS settings app.
Test Notification from console
I've tried sending a Test Notification in from Notification Composer, using a the recent FCM token for the test device, but this notification doesn't show up either, and it doesn't give me any feedback on screen whether the notification is successfully sendt or not.
What am I doing wrong here?
Any Suggestions to how I can debug this issue?
When we are working with Push Notification then it is very harder to debug issue.
As per my experience, there is nothing wrong with your typescript or iOS code because earlier it was worked perfectly. Below is the possible reason if the push notification is not working.
Generally, the APNS related issue occurs due to the certificate.
Make sure you are uploading the correct APNS profile to the firebase
console for both development and release mode.
Make sure you have enabled the notification in capabilities.
Your Project -> capabilities -> turn on Push Notifications
Make sure you're added correct GoogleService-Info.plist to the
project.
APNS Certificate is not expired.
Make sure you're using the latest version of the firebase.
Your device time should be automatic, not feature time.
If you still think it is code related issue and the above solution is not working then you can go with the below wrapper class of HSAPNSHelper class which is created by me and it is working for iOS 10 and later .
import Foundation
import UserNotifications
import Firebase
class HSAPNSHelper: NSObject {
static let shared = HSAPNSHelper()
let local_fcm_token = "local_fcm_token"
var notificationID = ""
func registerForPushNotification(application:UIApplication){
FirebaseApp.configure()
self.getFCMToken()
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().requestAuthorization(options: [.badge, .alert, .sound]) { (granted, error) in
DispatchQueue.main.async {
self.getFCMToken()
}
}
application.registerForRemoteNotifications()
}
}
extension HSAPNSHelper:UNUserNotificationCenterDelegate {
fileprivate func getFCMToken() {
InstanceID.instanceID().instanceID(handler: { (result, error) in
if error == nil, let fcmToken = result?.token{
print("FCM Token HS: \(fcmToken)")
UserDefaults.standard.set(fcmToken, forKey: self.local_fcm_token)
}
})
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("didFailToRegisterForRemoteNotificationsWithError : \(error)")
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
var token = ""
for i in 0..<deviceToken.count {
token = token + String(format: "%02.2hhx", arguments: [deviceToken[i]])
}
Messaging.messaging().apnsToken = deviceToken
getFCMToken()
}
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
let userInfo = notification.request.content.userInfo as! [String: Any]
print(userInfo)
completionHandler([.alert, .badge, .sound])
}
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
print(userInfo)
self.notificationRedirection()
}
private func notificationRedirection(){
}
func fcmToken() -> String{
return UserDefaults.standard.string(forKey:local_fcm_token) ?? ""
}
}
How to use?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
//For Push notification implementation
HSAPNSHelper.shared.registerForPushNotification(application: application)
return true
}
Use fcmToken() to get current FCM token.
I have created a sample ios application as per the instructions provided in the Firebase console to receive cloud messages on ios devices. Notification message is sent from the console and gets printed on the app console as well. But the push notification is not received on the device even after giving necessary permission.
I'm using swift 3 and xCode version 10.3. Registered the app in Firebase console and required FCM token is received through the app and added to send a test message to the device. Tried sending lot of messages through the console but none of them are shown on the device. It shows as the messages are being sent successfully on the console.
Following is my AppDelegate.swift file that I have written to receive the push notification.
import UIKit
import UserNotifications
import Firebase
import FirebaseMessaging
import FirebaseInstanceID
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
let gcmMessageIDKey = "gcm.message_id"
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if #available(iOS 10.0, *) {
FirebaseApp.configure()
Messaging.messaging().delegate = self
Messaging.messaging().shouldEstablishDirectChannel = true
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)
}
// request permission from user to send notification
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound], completionHandler: { authorized, error in
if authorized {
DispatchQueue.main.async(execute: {
application.registerForRemoteNotifications()
})
}
else{
print("Notification access denied")
}
})
return true
}
// [START receive_message]
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
print(userInfo)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
print(userInfo)
completionHandler(UIBackgroundFetchResult.newData)
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("Unable to register for remote notifications: \(error.localizedDescription)")
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Messaging.messaging().apnsToken = deviceToken
print("APNs token retrieved: \(deviceToken)")
}
}
#available(iOS 10, *)
extension AppDelegate : UNUserNotificationCenterDelegate {
// Receive displayed notifications for iOS 10 devices.
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
let userInfo = notification.request.content.userInfo
print(userInfo)
print("Message ID: \(userInfo["gcm.message_id"]!)")
completionHandler(UNNotificationPresentationOptions.alert)
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
print("Do what ever you want")
// Print full message.
print("tap on on forground app",userInfo)
completionHandler()
}
}
extension AppDelegate : MessagingDelegate {
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
print("Firebase registration token: \(fcmToken)")
Messaging.messaging().subscribe(toTopic: "/topics/nutriewell_live")
Messaging.messaging().shouldEstablishDirectChannel = true
}
func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) {
print("Received data message: \(remoteMessage.appData)")
}
}
I expected a push notification on the ios device but I'm not receiving any.
I'm getting the following output which gets printed with the notification message sent from the console.
2019-08-15 11:20:32.548066+0530 FirebaseIos[800:207059] - <AppMeasurement>[I-ACS036002] Analytics screen reporting is enabled. Call +[FIRAnalytics setScreenName:setScreenClass:] to set the screen name or override the default screen class name.
To disable screen reporting, set the flag FirebaseScreenReportingEnabled to NO (boolean) in the Info.plist
2019-08-15 11:20:32.949393+0530 FirebaseIos[800:207068] 6.2.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.
Firebase registration token: fsyB51mCvbg:APA91bFvRFPIxauHfKA-v-K29YTWl_TYFTgCpnvODrFA2rG8qN-F8vcLIWcZ-lOChkJw-pIBVhcxg2epBz7AYVALMNLC4Hs6M4ds_pQXytYymjr15KMqOt08_7PkmYkU1jHy6xcw5hvx
2019-08-15 11:20:34.914040+0530 FirebaseIos[800:207059] 6.2.0 - [Firebase/Messaging][I-FCM002024] Format '/topics/nutriewell_live' is deprecated. Only 'nutriewell_live' should be used in subscribeToTopic.
Notification access denied
2019-08-15 11:20:48.869741+0530 FirebaseIos[800:207068] [BoringSSL] nw_protocol_boringssl_get_output_frames(1301) [C7.1:2][0x101537e10] get output frames failed, state 8196
Received data message: [AnyHashable("notification"): {
body = "firebase ios";
e = 1;
tag = "campaign_collapse_key_3627158360856700759";
title = "firebase!";
}, AnyHashable("from"): 591363996390, AnyHashable("collapse_key"): com.combank.Firebase.Ios]
%# [AnyHashable("notification"): {
body = "firebase ios";
e = 1;
tag = "campaign_collapse_key_3627158360856700759";
title = "firebase!";
}, AnyHashable("from"): 591363996390, AnyHashable("collapse_key"): com.combank.Firebase.Ios]
Received data message: [AnyHashable("collapse_key"): com.combank.Firebase.Ios, AnyHashable("from"): 591363996390, AnyHashable("notification"): {
body = "firebase ios";
e = 1;
tag = "campaign_collapse_key_750970355066402639";
title = "firebase!";
}]
%# [AnyHashable("collapse_key"): com.combank.Firebase.Ios, AnyHashable("from"): 591363996390, AnyHashable("notification"): {
body = "firebase ios";
e = 1;
tag = "campaign_collapse_key_750970355066402639";
title = "firebase!";
}]
2019-08-15 11:22:34.475335+0530 FirebaseIos[800:207131] [BoringSSL] nw_protocol_boringssl_get_output_frames(1301) [C1.1:2][0x1015273f0] get output frames failed, state 8196
Any help I can get here for this?
There are two ways to receive notification:
when the app is closed/inactive and you get the payload in didFinishLaunchingWithOptions:
when the application is open/active and currently visible you get payload in didReceiveRemoteNotification:
When your application is closed, iOS take care of displaying a notification (if notification extension not developed) and launch your app when you tap on it.
If your application is open you have to take care of displaying this notification or ignore it.
Here what official documentation says:
When local and remote notifications are not handled directly by your
app or the user, they are displayed in Notification Center so that
they can be viewed later. Use the
getDeliveredNotificationsWithCompletionHandler: method of the shared UNUserNotificationCenter object to get a list of
notifications still being displayed in Notification Center. If you
find any notifications that are now outdated and should not be
displayed to the user, you can remove them using the
removeDeliveredNotificationsWithIdentifiers: method.
official documentation
We are running into a confusing issue when using Apple's Push Notifications via APN. We have the following scenario (quite standard i guess):
When our App, let's call it "MyApp" here, is installed and started for the first time we are asking the user for permissions to send him Push Notifications through "MyApp".
In this example the AppDelegate looks like this:
import UIKit
import UserNotifications
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Register Remote Notifications
UNUserNotificationCenter.current().delegate = self
self.registerForPushNotifications()
return true
}
// MARK: - Remote Notifications
func registerForPushNotifications() {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { (granted, error) in
guard granted else {
return
}
self.getNotificationSettings()
}
}
func getNotificationSettings() {
UNUserNotificationCenter.current().getNotificationSettings { (settings) in
guard settings.authorizationStatus == .authorized else {
return
}
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
}
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let tokenParts = deviceToken.map { (data) -> String in
return String(format: "%02.2hhx", data)
}
let token = tokenParts.joined()
print("ApnToken: \(token)")
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("did Fail to Register for RemoteNotifications")
}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
print("willPresentNotification!")
completionHandler([.badge, .sound, .alert])
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
print("UserDidResponseToNotification!")
completionHandler()
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
print("DidReceiveRemoteNotification!")
completionHandler(.newData)
}
}
So the user installs and the starts the app and is asked if "MyApp" is allowed to send the user Push Notifications. If the user accepts the Push Notifications application(_:didRegisterForRemoteNotificationsWithDeviceToken:) is called and we give the received deviceToken to our API.
Now the part that confuses me:
The user also has the option to turn Push Notifications off later via the iPhone-Settings like this: Settings > "MyApp" > Notifications > Allow Notifications > Turns the Switch off
Our API has now the deviceToken for APN but the user turned Push Notifications off via iPhone-Settings.
The "problem":
After the user turned off Push Notifications we are still able to send silent Push Notifications to the device and "MyApp" gets the data correct without any problems.
But in the other scenario: The User installs and starts "MyApp" and declines at the first start Push Notifications it is not possible to get a deviceToken from Apple. I tried to get a deviceToken from Apple even if the user declined the Push Notification Alert like this: (But this doesn't work - I guess Apple doesn't provide my any if the user declines)
func registerForPushNotifications() {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { (granted, error) in
self.getNotificationSettings()
}
}
func getNotificationSettings() {
UNUserNotificationCenter.current().getNotificationSettings { (settings) in
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
}
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let tokenParts = deviceToken.map { (data) -> String in
return String(format: "%02.2hhx", data)
}
let token = tokenParts.joined()
print("ApnToken: \(token)")
}
It seems like it doesn't matter what the user does if he accepts Push Notifications at the first start. I mean ok, we cannot show the Information via Banner or anything to the user but we can transfer data to the device using APN's even if the user did turn off this setting at a later time. (But we cannot send anything if he declines at start of the app - we need a deviceToken once)
Am i misunderstanding a thing here? This seems inconsistent to me.
I tried to clarify my question so everyone can understand what i am asking for. Excuse my "bad" english it is not easy as a non-native-speaker to ask specific questions with a lot of context here. Anyway, if you need further informations or you didn't understand one or more points from what i am asking let me know i will provide detailed informations and will clarify my question.
I don't know if this matters but at the moment we are using an APN-Development-Certificate (not a distribution certificate yet)
Good question,
The thing is that if user allows you to send push notification (gives you his/her device token) you would be able to send pushes. The push data via notification could be send without notification for a user (silence notification) you could read more about it here: https://medium.com/#m.imadali10/ios-silent-push-notifications-84009d57794c
That's why you are able to send push even if user prevents notification from displaying. That settings controls only displaying appearance, but since he/she gives you the token you still could send data to them. There actually no way for a user to disable that token after it was granted.
I have recently updated to Xcode 8.3.2 and push stopped working; although I did not change anything but only upgraded swift version to current one
In my Firebase console, when I send to all iOS swift devices (I got only one registered) stats shows 0 (screenshot http://joxi.ru/Y2LBBaVH39alr6)
The push token I get is
cGH1MCWEvr8:APA91bFxQkydAWsmdyCHEKma-jSn9wS6Ub_bxRCDVR3nFx-9URNLRifeRxS_nnD_kgM5P5J6bH2vQK2e1RwxCi1PzbPrwW7WU2qjQc-KhRVlX6V5VBl3bKzgQgjNnh-C4Y8OgiOcJQpt
And this is what I got when sending to certain device (screenshot http://joxi.ru/eAOGGOVuyxOBAo)
Any help is appreciated.
Not sure if this will help but to avoid deprecated code for iOS 10+ (Swift 3.1.1 and XCode 8.3.2) this is a sample AppDelegate.swift file to get push notifications working. (Note: In addition to enabling Push Notifications, you must also enable Remote Notifications in Background Modes under the Capabilities menu in your XCode project.)
import UIKit
import Firebase
import FirebaseInstanceID
import FirebaseMessaging
import UserNotifications
#UIApplicationMain
class AppDelegate: UIResponder,UIApplicationDelegate,UNUserNotificationCenterDelegate{
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
//create the notificationCenter
if #available(iOS 10.0, *) {
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in })
// For iOS 10 data message (sent via FCM)
//FIRMessaging.messaging().remoteMessageDelegate = self
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
FirebaseApp.configure()
return true
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
var token = ""
for i in 0..<deviceToken.count {
token = token + String(format: "%02.2hhx", arguments: [deviceToken[i]])
}
print("Registration succeeded! Token: ", token)
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("Registration failed!")
}
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.
UIApplication.shared.applicationIconBadgeNumber = 0
}
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.
}
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.
}
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.
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
// Firebase notification received
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (_ options: UNNotificationPresentationOptions) -> Void) {
// custom code to handle push while app is in the foreground
print("Handle push from foreground\(notification.request.content.userInfo)")
let dict = notification.request.content.userInfo["aps"] as! NSDictionary
let d : [String : Any] = dict["alert"] as! [String : Any]
let body : String = d["body"] as! String
let title : String = d["title"] as! String
print("Title:\(title) + body:\(body)")
self.showAlertAppDelegate(title: title,message:body,buttonTitle:"ok",window:self.window!)
}
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
// if you set a member variable in didReceiveRemoteNotification, you will know if this is from closed or background
print("Handle push from background or closed\(response.notification.request.content.userInfo)")
}
func showAlertAppDelegate(title: String,message : String,buttonTitle: String,window: UIWindow){
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: buttonTitle, style: UIAlertActionStyle.default, handler: nil))
window.rootViewController?.present(alert, animated: false, completion: nil)
}
// Firebase Code Ends
}
For assistance with migrating code to the latest Firebase changes, visit this link:
Firebase Migration 2017
I hope this helps or points you in the right direction!
01010011 01010000 01000101 01000011 01010100 01010010 01000101