Apple Push Notifications in tvOS - ios

Hi i am a newbie to tvOS. I have an TV application which is registered for APNS.
But while i push a notification i am not able to get the notifications.
i am getting the device token but not the notification.
While i try with the Mobile Devices i am getting the notifications,But not in the tvOS why is it so...?
How can i solve this..?
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .sound, .badge]) { (granted, error) in
if granted == true
{
print("Allow")
UIApplication.shared.registerForRemoteNotifications()
}
else
{
print("Don't Allow")
}
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
print("DEVICE TOKEN = \(deviceTokenString)")
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print(error)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
print(userInfo)
}

tvOS supports only 2 types of notifications: badges and content-available. So you need to send one of these two types to APNS. Any of these types notification only changes badge number on App Icon. And only the lastest notification will be delivered to your application when you open the app. There is no visual presentation of notification as it was on iOS
How it looks see on presentation from WWDC 2016/Session 206/tvOS, start watching from 21:20
UPDATE:
On tvOS 11 appeared Silent notifications which wakes the application up and allow to refresh content in background
WWDC 2017 watch from 7:50

This is my solution for Notifications in tvOS.
in AppDelegate
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
// set self (AppDelegate) to handle notification
UNUserNotificationCenter.current().delegate = self
// 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()
})
}
})
return true
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
//print(userInfo)
print("Notification Received")
let nc = NotificationCenter.default
nc.post(name: Notification.Name("foo"), object: nil)
}
The first function provide the permission necessary for notification.
And the second function received the notification and send a notification to the current viewcontroller and make the magic happpend.
This is the viewcontroller
//viewload NotificationCenter.default.addObserver(self, selector: #selector(updateTable(_ :)), name: Notification.Name("foo"), object: nil)

Related

Why can't I get a push message in Swift5?

I am currently trying to get a push message. However, you cannot receive a push message. What am I missing?
AppDelegate
import UIKit
import UserNotifications
import Firebase
import FirebaseMessaging
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
self.window = UIWindow(frame: UIScreen.main.bounds)
// 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 })
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
FirebaseApp.configure()
Messaging.messaging().delegate = self
return true
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let token = deviceToken.map{ String(format: "%02x", $0) }.joined()
Log.Info("Registration succeeded!")
Log.Info("Token: \(token)")
LocalStorage.set(token, "dacDeviceToken")
Messaging.messaging().apnsToken = deviceToken
InstanceID.instanceID().instanceID { (result, error) in
if let error = error {
Log.Error("Error fetching remote instance ID: \(error)")
} else if let result = result {
Log.Info("Remote instance ID token: \(result.token)")
}
}
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
Log.Warning("Registration failed!")
}
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"] {
Log.Info("Message ID: \(messageID)")
}
// Print full message.
Log.Info(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"] {
Log.Info("Message ID: \(messageID)")
}
// Print full message.
Log.Info(userInfo)
completionHandler(UIBackgroundFetchResult.newData)
}
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.
}
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:.
}
func getNotificationSettings() {
UNUserNotificationCenter.current().getNotificationSettings { settings in
print("Notification settings: \(settings)")
guard settings.authorizationStatus == .authorized else { return }
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
}
}
}
#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 message ID.
Log.Info("Message ID: \(userInfo["gcm.message_id"]!)")
// Print full message.
print("%#", userInfo)
Log.Info(userInfo)
}
}
extension AppDelegate : MessagingDelegate {
// Receive data message on iOS 10 devices.
func applicationReceivedRemoteMessage(_ remoteMessage: MessagingRemoteMessage) {
print("%#", remoteMessage.appData)
}
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
Log.Info("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.
}
}
my Log
2019-09-24 19:31:46.519806+0900 test[586:74065] -
[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-09-24 19:31:46.756433+0900 test[586:74071]
6.9.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:
to ensure proper integration. 2019-09-24 19:31:46.759687+0900
test[586:74071] 6.9.0 - [Firebase/Analytics][I-ACS023007] Analytics
v.60102000 started 2019-09-24 19:31:46.760699+0900 test[586:74071]
6.9.0 - [Firebase/Analytics][I-ACS023008] To enable debug logging set the following application argument: -FIRAnalyticsDebugEnabled INFO: 2019-09-24 10:31:46 +0000 -
AppDelegate.swift messaging(_:didReceiveRegistrationToken:) [Line:196]
Firebase registration token:
dZ4US-5dJqk:APA91bF0-****************
INFO: 2019-09-24 10:31:46 +0000 - AppDelegate.swift
application(_:didRegisterForRemoteNotificationsWithDeviceToken:)
[Line:82] Registration succeeded! INFO: 2019-09-24 10:31:46 +0000 -
AppDelegate.swift
application(:didRegisterForRemoteNotificationsWithDeviceToken:)
[Line:83] Token:
213eba827****************************** INFO:
2019-09-24 10:31:46 +0000 - AppDelegate.swift
application(:didRegisterForRemoteNotificationsWithDeviceToken:)
[Line:90] Remote instance ID token:
dZ4US-5dJqk:APA91bF0-77***********
2019-09-24 19:31:46.921546+0900 test[586:74071] [MC] System group
container for systemgroup.com.apple.configurationprofiles path is
/private/var/containers/Shared/SystemGroup/systemgroup.com.apple.configurationprofiles
2019-09-24 19:31:46.923537+0900 test[586:74071] [MC] Reading from
public effective user settings.
Send Test FCM
I don't get anything. My app doesn't receive push messages whether it's in the foreground or in the background.
Please help me a lot.
The token you added in the figure is the device token value. Token values are visible in the log.
EDIT
I saw the answer and followed it, but it doesn't work.
Can you Put GoogleService-Info.plist file in your project?
Try This In My Code 100% Working
import Firebase
import FirebaseCore
import FirebaseMessaging
import UserNotifications
import UserNotificationsUI
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate , MessagingDelegate{
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
Messaging.messaging().delegate = self
FirebaseApp.configure()
//Register App For Push Notification
self.registerAppForPushNotificaition()
application.registerForRemoteNotifications()
return true
}
func registerAppForPushNotificaition(){
if #available(iOS 10.0, *) {
let center = UNUserNotificationCenter.current()
let inviteCategory = UNNotificationCategory(identifier: "Notification", actions: [], intentIdentifiers: [], options: UNNotificationCategoryOptions.customDismissAction)
let categories = NSSet(objects: inviteCategory)
center.delegate = self
center.setNotificationCategories(categories as! Set<UNNotificationCategory>)
center.requestAuthorization(options: [.sound, .badge, .alert], completionHandler: { (granted, error) in
if !(error != nil){
DispatchQueue.main.async(execute: {
UIApplication.shared.registerForRemoteNotifications()
})
}
})
} else {
UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types:[.sound , .alert , .badge] , categories: nil))
UIApplication.shared.registerForRemoteNotifications()
}
}
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void)
{
completionHandler(.alert)
}
func application(_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Auth.auth().setAPNSToken(deviceToken, type: AuthAPNSTokenType.sandbox)
Messaging.messaging().apnsToken = deviceToken
let token = InstanceID.instanceID().token()
if token != nil {
fcmID = token!
}
}
func application(application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
Messaging.messaging().apnsToken = deviceToken as Data
// print(deviceToken)
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
NSLog("Failed to get Access Token: \(error)")
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
if Auth.auth().canHandleNotification(userInfo) {
completionHandler(UIBackgroundFetchResult.noData)
return
}
completionHandler(UIBackgroundFetchResult.newData)
}
func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String) {
print("fcmToken \(fcmToken)")
}
func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) {
print("remort \(remoteMessage.appData)")
}
I saw the answer and followed it, but it doesn't work. However, when you added a new project on the Fire Base, added the iOS app again, and tried, it was successful. I'm not sure what's wrong. Was that a problem with my code?I thought, but when I used the code in the question,also it worked. I simply created and added a new project for my solution.

How to call API when app is terminated in push notifcation iOS Swift?

We are working on push notification. We need to call the web service when we get a notification in active, background, foreground and terminated. But when we terminated the app we get a notification but can’t able to call the web service. The reason for calling the web service is to identify the message was received for a mobile app.
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
if ( application.applicationState == .inactive || application.applicationState == .background ) {
**// Need to call API**
}
}
Is any other way to identify the message was delivered in mobile app in the server side?
As per Apple guidelines, you can get push notification for the background as well as on foreground state but when it comes to
Terminate state apple don't allow you to automatically open the app or
do any kind of operation unless you launch the app through notification.
Though you can handle notification during the Terminated state using Launch Options at the time of app launch.
Coding Example:
In your AppDelegate.swift import firebase library
import Firebase
import FirebaseInstanceID
import FirebaseMessaging
import UserNotifications
Whenever app launch register for push notification service, add the following lines of code into your didFinishLaunchingWithOptions
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
registerForPushNotifications(application: application)
handleNotificationWhenAppIsKilled(launchOptions)
return true
}
func handleNotificationWhenAppIsKilled(_ launchOptions: [UIApplicationLaunchOptionsKey: Any]?) {
// Check if launched from the remote notification and application is close
if let remoteNotification = launchOptions?[.remoteNotification] as? [AnyHashable : Any] {
// Handle your app navigation accordingly and update the webservice as per information on the app.
}
}
Add extension methods of appDelegate to register for remote notification and to get device token from APNS
//MARK: - Notifications related...
extension AppDelegate {
func registerForPushNotifications(application: UIApplication) {
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
Messaging.messaging().delegate = self
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
let savedAPNSToken = UserDefaults.standard.object(forKey: "savedAPNSToken") as? String
if savedAPNSToken != token {
UserDefaults.standard.set(token, forKey: "savedAPNSToken")
UserDefaults.standard.synchronize()
Messaging.messaging().apnsToken = deviceToken
}
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print(error.localizedDescription)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
completionHandler(UIBackgroundFetchResult.newData)
}
}
Use the following methods of notificationCenter to handle notification in the foreground and background states :
// MARK: - UNUserNotificationCenterDelegate
#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
completionHandler([.alert])
}
/// Handle tap on the notification banner
///
/// - Parameters:
/// - center: Notification Center
/// - response: Notification response
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
completionHandler()
}
Firebase token renewel:
extension AppDelegate : MessagingDelegate {
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
// Note: This callback is fired at each app startup and whenever a new token is generated.
let savedFCMToken = UserDefaults.standard.object(forKey: "savedFCMToken") as? String
if savedFCMToken != fcmToken {
UserDefaults.standard.set(fcmToken, forKey: "savedFCMToken")
UserDefaults.standard.synchronize()
// Update FCMToken to server by doing API call...
}
}
}
We have a option called silent notification check below link
https://medium.com/#m.imadali10/ios-silent-push-notifications-84009d57794c
Check the link below this is what you require.
https://samwize.com/2015/08/07/how-to-handle-remote-notification-with-background-mode-enabled/
You need to activate background mode for push notification. The full process is been explained in the above article.

how to setting up AppDelegate for push notification in swift

I am trying to setup a push notification system for my application. I have a server and a developer license to setup the push notification service.
I am currently running my app in Swift4 Xcode 9
here are my questions :
1_ is that possible that I set the title and body of notification massage ??
2_ what is the func of receiving massage ? I'm using didReceiveRemoteNotification but this is called when I touch the notification I need a func which is called before showing notification that I can set my massage on it
3_ I'm generating device token in appDelegate and also in my login page for my server which are different from each other. this is not correct right ?
this is my app delegate :
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
print("lunch",launchOptions?.description,launchOptions?.first)
application.registerForRemoteNotifications()
FirebaseApp.configure()
GMSPlacesClient.provideAPIKey("AIzaSyAXGsvzqyN3ArpWuycvQ5GS5weLtptWt14")
UserDefaults.standard.set(["fa_IR"], forKey: "AppleLanguages")
UserDefaults.standard.synchronize()
registerForPushNotifications()
return true
}
func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) {
print("test : ",messaging.apnsToken)
}
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
print("Recived: \(userInfo)")
print()
// completionHandler(.newData)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
print("userInfo : ",userInfo)
if application.applicationState == .active {
print("active")
//write your code here when app is in foreground
} else {
print("inactive")
//write your code here for other state
}
}
func getNotificationSettings() {
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().getNotificationSettings { (settings) in
print("Notification settings: \(settings)")
guard settings.authorizationStatus == .authorized else { return }
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
}
} else {
}
}
func registerForPushNotifications() {
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) {
(granted, error) in
print("Permission granted: \(granted)")
guard granted else { return }
self.getNotificationSettings()
}
} else {
let settings = UIUserNotificationSettings(types: [.alert, .sound, .badge], categories: nil)
UIApplication.shared.registerUserNotificationSettings(settings)
UIApplication.shared.registerForRemoteNotifications()
// self.getNotificationSettings()
}
}
Yes, you can manage the content of notification by sending an appropriate payload in the notification. Sending the payload in the following pattern would show title and body in the notification
{
"aps" : {
"alert" : {
"title" : "Game Request",
"body" : "Bob wants to play poker",
},
"badge" : 5
}
}
Display the notification is handled by the system depending upon the app state. If the app is the foreground state you will get the call in the didReceiveRemoteNotification, otherwise, the system handles the displaying part and get control in the app when the user taps on the notification.
You cannot edit the content of notification from the app side.
According to the document
APNs can issue a new device token for a variety of reasons:
User installs your app on a new device
User restores device from a backup
User reinstalls the operating system
Other system-defined events
So its recommended requesting device token at launch time.
You can send the token in login page rather than requesting a new token in the login.

application:didRegisterForRemoteNotificationsWithDeviceToken: not called ios 10.3.2

I want to develop a simple code which use push notifications. I create certificates and provision profiles based on existing tutorials, such as link, and this, but the register function application:didRegisterForRemoteNotificationsWithDeviceToken: is not called at all, thus I can't get device token.
I also turned on Push notification and Remote notification for background in Capabilities tab in xcode. here is my code in AppDelegate.swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
UNUserNotificationCenter.current().requestAuthorization(options:[.badge, .alert, .sound]){ (granted, error) in }
UIApplication.shared.registerForRemoteNotifications()
return true
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
print("APNs device token: \(deviceTokenString)")
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("APNs registration failed: \(error)")
}
func application(_ application: UIApplication, didReceiveRemoteNotification data: [AnyHashable : Any]) {
print("Push notification received: \(data)")
}
I am working with an iPhone 5s running iOS 10.3.2
Please call registerForNotifications from didFinishLaunchingWithOptions method in AppDelegate
//MARK:- Methods
func registerForNotifications(){
if #available(iOS 10.0, *) {
let center = UNUserNotificationCenter.current()
center.delegate = self
center.requestAuthorization(options:[.alert,.sound]) { (granted, error) in
if granted{
UIApplication.shared.registerForRemoteNotifications()
}else{
print("Notification permission denied.")
}
}
} else {
// For ios 9 and below
let type: UIUserNotificationType = [.alert,.sound];
let setting = UIUserNotificationSettings(types: type, categories: nil);
UIApplication.shared.registerUserNotificationSettings(setting);
UIApplication.shared.registerForRemoteNotifications()
}
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let token = String(format: "%#", deviceToken as CVarArg).trimmingCharacters(in: CharacterSet(charactersIn: "<>")).replacingOccurrences(of: " ", with: "")
print(token)
}
I couldn't find why it wasn't called, but when I changed my test target to an iPhone 7 which is running iOS 10.3.2, it worked fine.
I'm not sure why it is happening, but changing your target may solve the problem

Why I do not get push notifications from Firebase in Swift?

I set this code in my AppDelegate:
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate, FIRMessagingDelegate {
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
if #available(iOS 10.0, *) {
let authOptions: UNAuthorizationOptions = [.Alert, .Badge, .Sound]
UNUserNotificationCenter.currentNotificationCenter().requestAuthorizationWithOptions(authOptions, completionHandler: { (granted: Bool, error: NSError?) in
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.currentNotificationCenter().delegate = self
// For iOS 10 data message (sent via FCM)
FIRMessaging.messaging().remoteMessageDelegate = self
})
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
application.registerUserNotificationSettings(UIUserNotificationSettings(forTypes: [.Alert, .Sound, .Badge], categories: nil))
}
Also this parts:
internal func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
print(userInfo)
// 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
// Print message ID.
print("Message ID: \(userInfo["gcm.message_id"]!)")
// Print full message.
print(userInfo)
}
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject],
fetchCompletionHandler completionHandler: (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
// Print message ID.
print("Message ID: \(userInfo["gcm.message_id"]!)")
// Print full message.
print(userInfo)
}
#available(iOS 10.0, *)
func userNotificationCenter(center: UNUserNotificationCenter, willPresentNotification notification: UNNotification, withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void) {
//Handle the notification
}
#available(iOS 10.0, *)
func userNotificationCenter(center: UNUserNotificationCenter, didReceiveNotificationResponse response: UNNotificationResponse, withCompletionHandler completionHandler: () -> Void) {
//Handle the notification
}
I also uploaded development APNs into the Apple Developers. In the Firebase console it writes that notification was successfully sent, but I do not get any push notification. Can anyone please help me to detect where my mistake is?
I have worked on it for 3 days. Searched a lot, but nothing.
Add FIRApp.configure() to the didFinishLaunchingWithOptions:
Add FIRMessaging.messaging().connect { (error) in
if error != nil {
print("Unable to connect with FCM. \(error)")
} else {
print("Connected to FCM.")
} to the end of didFinishLaunchingWithOptions:
Implement the FIRMessageDelegate function
func applicationReceivedRemoteMessage(_ remoteMessage: FIRMessagingRemoteMessage) {
print(remoteMessage.appData)
}
Add FIRMessaging.messaging().appDidReceiveMessage(userInfo) to func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void)
The finishing code should look like this:
import UIKit
import Firebase
import UserNotifications
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate, FIRMessagingDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
FIRApp.configure()
if #available(iOS 10.0, *) {
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in })
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self
// 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)
}
FIRMessaging.messaging().connect { (error) in
if error != nil {
print("Unable to connect with FCM. \(error)")
} else {
print("Connected to FCM.")
}
}
application.registerForRemoteNotifications()
return true
}
func applicationReceivedRemoteMessage(_ remoteMessage: FIRMessagingRemoteMessage) {
print("applicationReceivedRemoteMessage ")
print(remoteMessage.appData)
}
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
// Print message ID.
print("Message ID: \(userInfo["gcm.message_id"]!)")
// 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
// Print message ID.
print("Message ID: \(userInfo["gcm.message_id"]!)")
// Print full message.
print(userInfo)
FIRMessaging.messaging().appDidReceiveMessage(userInfo)
}
For anyone still looking, check the last answer here: ios10, Swift 3 and Firebase Push Notifications (FCM)
Check your push notification entitlement and switch it on. Target > Capabilities > Push notifications.

Resources