iOS Push Notification Action Button Doesn't Appear - ios

I'm trying to add action button for push notification. Actually, It is adding successfully when I build the app and give permission for notifications first time.
The problem begins after when I killed the app and trying to send notification again. Notification is receiving but action button doesn't appear. I think I don't define setNotificationCategories() method in right place but I can't find right solution for this issue. Here is my code: (Thanks for any help)
AppDelegate:
import UIKit
import UserNotifications
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate{
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) {(granted, error) in
if !granted {
print("Notification access denied.")
}
setNotificationCategory()
}
if #available(iOS 10.0, *) {
setNotificationCategory()
UNUserNotificationCenter.current().delegate = self
}
return true
}
func applicationWillResignActive(_ application: UIApplication) {
}
func applicationDidEnterBackground(_ application: UIApplication) {
}
func applicationWillEnterForeground(_ application: UIApplication) {
}
func applicationDidBecomeActive(_ application: UIApplication) {
}
func applicationWillTerminate(_ application: UIApplication) {
}
}
#available(iOS 10.0, *)
extension AppDelegate: UNUserNotificationCenterDelegate{
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
if response.notification.request.content.categoryIdentifier == Constants.Notification.Category.general{
if response.actionIdentifier == Constants.Notification.Action.likeAction{
if let notificationID = response.notification.request.content.userInfo["notification_id"]{
NotificationActionHandler.likeActionHandler(notificationID: notificationID as! Int)
}
}
}
completionHandler()
}
func setNotificationCategory(){
let likeAction = UNNotificationAction(identifier: Constants.Notification.Action.likeAction, title: "❤️", options: [])
let generalCategory = UNNotificationCategory(identifier: Constants.Notification.Category.general, actions: [likeAction], intentIdentifiers: [], options: .customDismissAction)
let center = UNUserNotificationCenter.current()
center.setNotificationCategories([generalCategory])
}
}
NotificationActionHandler:
import Foundation
class NotificationActionHandler{
class func likeActionHandler(notificationID: Int){
print("liked! ❤️ \(notificationID)")
}
}

Related

I cannot implement Firebase Notifications into Flutter on Ios

I did exactly the same things in google's documentation but it does not work. I faced with "No such module 'Flutter'" Here is the code example:
import UIKit
import Flutter
import Firebase
#UIApplicationMain
#objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
FirebaseApp.configure()
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
And also, I find something. You can see from below. It is kind of working but not properly working. While it was opening, it wanted my permission for notifications. But it gives me a black screen. I cannot see anything. Here are the code parts:
import UIKit
import FirebaseCore
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions:
[UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// Firebase
FirebaseApp.configure()
// Push Notification
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: { _, _ in }
)
application.registerForRemoteNotifications()
return true
}
}
extension AppDelegate: UNUserNotificationCenterDelegate {}
According to an idea:
This is my AppDelegate.swift file. I'm trying to apply your response.
import UserNotifications
import Firebase
import FirebaseMessaging
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions:
[UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// Firebase
FirebaseApp.configure()
// Push Notification
UNUserNotificationCenter.current().delegate = self
registerForPushNotifications() // Function created below
return true
}
func registerForPushNotifications() {
UNUserNotificationCenter.current()
.requestAuthorization(
options: [.alert, .sound, .badge]) { [weak self] granted, _ in
print("Permission granted: \(granted)")
guard granted else { return }
self?.getNotificationSettings()
}
}
// MARK:- Get Notification
func getNotificationSettings() {
UNUserNotificationCenter.current().getNotificationSettings { settings in
print("Notification settings: \(settings)")
guard settings.authorizationStatus == .authorized else { return }
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
}
}
}
extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void)
{
completionHandler([.alert, .badge, .sound])
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
print(userInfo)
completionHandler()
}
}
This is the output that I mentioned before:
Install a pod :- pod 'FirebaseMessaging'
-> goto AppDelegate:
import UserNotifications
import Firebase
import FirebaseMessaging
-> on didFinishLaunchingWithOptions
UNUserNotificationCenter.current().delegate = self
registerForPushNotifications() // Function created below
-> Create functions to accept Notification permission
func registerForPushNotifications() {
UNUserNotificationCenter.current()
.requestAuthorization(
options: [.alert, .sound, .badge]) { [weak self] granted, _ in
print("Permission granted: \(granted)")
guard granted else { return }
self?.getNotificationSettings()
}
}
// MARK:- Get Notification
func getNotificationSettings() {
UNUserNotificationCenter.current().getNotificationSettings { settings in
print("Notification settings: \(settings)")
guard settings.authorizationStatus == .authorized else { return }
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
}
}
-> delegate methods
extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void)
{
completionHandler([.alert, .badge, .sound])
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
print(userInfo)
completionHandler()
}
}
-> To get Device Token
func application(_ application: UIApplication,didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let tokenParts = deviceToken.map { data in String(format: "%02.2hhx", data) }
let token = tokenParts.joined()
Logger.log(logType: .info, object: token)
}
There is no problem with AppDelegate.swift file. I need to change main.dart file. No need to change anything more.
import UIKit
import Flutter
import Firebase
#UIApplicationMain
#objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
FirebaseApp.configure()
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}

Please implement -messaging:didReceiveRegistrationToken: to be provided with an FCM token

I am trying to put iOS push notifications onto my app. But keep getting the error
The object <FancyDeliveryManager.ViewController: 0x101910170> does not respond to -messaging:didReceiveRegistrationToken:. Please implement -messaging:didReceiveRegistrationToken: to be provided with an FCM token.
My app delegate looks like:
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate, MessagingDelegate {
var window : UIWindow?
//private let pushNotificationHandler: PushNotificationHandler = PushNotificationHandler()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
//notification delegates
Messaging.messaging().delegate = self //enables recievieving of tokens
UNUserNotificationCenter.current().delegate = self
///
//set up nav controller
let root: UIViewController = ViewController()
let navigationController = UINavigationController(rootViewController: root)
window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = navigationController
window?.makeKeyAndVisible()
return true
}
//MARK: Push Handling
func registerForPushNotifications() {
UNUserNotificationCenter.current()
.requestAuthorization(options: [.alert, .sound, .badge]) {
[weak self] granted, error in
guard granted else { return }
self?.getNotificationSettings()
}
}
//check the notification settings
func getNotificationSettings() {
UNUserNotificationCenter.current().getNotificationSettings { settings in
guard settings.authorizationStatus == .authorized else { return }
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
}
}
// 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])
}
//called when user interacts with push notification
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
print("Launched from push notification")
completionHandler()
}
// This callback is fired at each app startup and whenever a new token is created.
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
print("Firebase registration token: \(fcmToken)")
saveFcmToken(token: fcmToken)
}
//save token in database
func saveFcmToken(token: String){
var ref: DatabaseReference!
ref = Database.database().reference()
guard let userID = Auth.currentUser else { return }
ref.child("WarehouseManagers/\(userID)/fcmToken").setValue(token)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
//default to delegate method below
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
completionHandler(UIBackgroundFetchResult.newData)
}
// [END receive_message]
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("Unable to register for remote notifications: \(error.localizedDescription)")
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
print("APNs token retrieved: \(deviceToken)")
// With swizzling disabled you must set the APNs token here.
// Messaging.messaging().apnsToken = deviceToken
}
func applicationDidBecomeActive(_ application: UIApplication) {
UIApplication.shared.applicationIconBadgeNumber = 0
}
Is there something in the main ViewController that needs to be added here?
Any help would be greatly appreciated.

Rest Api Firebase Notification Won't Work In Swift 4 When App Is Closed

I've used apple push notification service in my app and I received certificates and it works well But now my problem is that when I use Firebase rest API for sending message as notification I won’t receive any notification in my iPhone until I run the app But when I use Firebase it will be working, well here is my codes:
import UIKit
import Firebase
import FirebaseMessaging
import FirebaseInstanceID
import UserNotifications
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
NotificationCenter.default.addObserver(self, selector: #selector(self.refreshToken(notification:)), name: NSNotification.Name.InstanceIDTokenRefresh, object: nil)
Messaging.messaging().isAutoInitEnabled = true
FirebaseApp.configure()
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert , .badge , .sound]) { (success, error) in
}
} else {
UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.badge, .sound, .alert], categories: nil))
UIApplication.shared.registerForRemoteNotifications()
// Fallback on earlier versions
}
application.registerForRemoteNotifications()
return true
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
#if PROD_BUILD
FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: .prod)
#else
InstanceID.instanceID().setAPNSToken(deviceToken, type: .sandbox)
#endif
Messaging.messaging().subscribe(toTopic: "global")
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
Messaging.messaging().subscribe(toTopic: "global")
print(userInfo)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
Messaging.messaging().appDidReceiveMessage(userInfo)
if Messaging.messaging().fcmToken != nil {
Messaging.messaging().subscribe(toTopic: "global")
}
// Print full message.
print(userInfo)
completionHandler(UIBackgroundFetchResult.newData)
}
func applicationDidEnterBackground(_ application: UIApplication) {
Messaging.messaging().shouldEstablishDirectChannel = false
}
func applicationDidBecomeActive(_ application: UIApplication) {
FBHandler()
}
#objc func refreshToken(notification : NSNotification) {
let refreshToken = InstanceID.instanceID().token()!
print("***\(refreshToken)")
FBHandler()
}
func FBHandler() {
Messaging.messaging().shouldEstablishDirectChannel = true
}
}
For APNS to work in background you need to enable background modes in capabilities section and tick remote notification.
Once you done add/check this delegate method in AppDelegate class
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
print("APNS USER INFO: \(userInfo)")
}
This method fires when app is in background and APNS comes.
More Info: How to handle push notification in background in ios 10?
UPDATE:
Add this one also and let see if it works
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void) {
print("APNS: \(response.notification.request.content.userInfo)")
}

Firebase Push Notifications

I've got FCM working, but I can't get the traditional banner notifications working.
Here's what I have in my AppDelegate.swift file:
import UIKit
import Firebase
import UserNotifications
#UIApplicationMain
final class AppDelegate: UIResponder {
var window: UIWindow?
override init() {
super.init()
FIRApp.configure()
}
}
// MARK: - UIApplicationDelegate
extension AppDelegate: UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(options: authOptions, completionHandler: { _, _ in })
UNUserNotificationCenter.current().delegate = self
FIRMessaging.messaging().remoteMessageDelegate = self
application.registerForRemoteNotifications()
NotificationCenter.default.addObserver(self, selector: #selector(tokenRefreshNotification), name: .firInstanceIDTokenRefresh, object: nil)
return true
}
func tokenRefreshNotification(notification: Notification) {
if let refreshedToken = FIRInstanceID.instanceID().token() {
print("InstanceID token: \(refreshedToken)")
}
connectToFcm()
}
func connectToFcm() {
FIRMessaging.messaging().connect { error in
if error != nil {
print("Unable to connect with FCM. \(error)")
} else {
print("Connected to FCM.")
}
}
}
func applicationDidBecomeActive(_ application: UIApplication) {
connectToFcm()
}
}
// MARK: - UNUserNotificationCenterDelegate
extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
let userInfo = notification.request.content.userInfo
print("Message ID: \(userInfo["gcm.message_id"]!)")
print(userInfo)
completionHandler([.alert, .sound])
}
}
// MARK:
extension AppDelegate: FIRMessagingDelegate {
func applicationReceivedRemoteMessage(_ remoteMessage: FIRMessagingRemoteMessage) {
print("FIRMessagingRemoteMessage Received: \(remoteMessage.appData)")
}
}
Everything is configured according to the documentation. I'm getting console outputs when I send messages to my app via the notifications console on Firebase.
However, banners don't appear when notifications are sent. When the app is backgrounded, notifications don't appear to be sent either - only when the app is in the foreground.
Looking for help. Thanks in advance!
Try disabling method swizzling.
Add FirebaseAppDelegateProxyEnabled to info.plist and set it to NO.
Then add this code to the app delegate
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenTypeSandbox)
}
Delete your app from the device and reinstall it.
please test if application:didRegisterForRemoteNotificationsWithDeviceToken is called. If its called, now try sending a notification from the firebase console.

iOS push notification via Firebase not working

Hello I'm making an iPhone app where I send push notifications via Google's Firebase. I'm using Swift and Xcode for the programming. When I open the app I get asked to allow push notifications, however I don't receive any when I send them from the Firebase Console. I was wondering if you could help me out. I'm using Ad Hoc export to transfer an .isa to my friend's iPhone and test it that way. I followed exactly the Firebase tutorial - adding the .plist, the cocoa pod and I uploaded a certificate in the project settings. I have a paid apple developer account.
import UIKit
import CoreData
import Firebase
import FirebaseMessaging
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
FIRApp.configure()
let notificationTypes: UIUserNotificationType = [UIUserNotificationType.Alert,UIUserNotificationType.Badge,UIUserNotificationType.Sound]
let notificationSettings = UIUserNotificationSettings(forTypes:notificationTypes, categories:nil)
application.registerForRemoteNotifications()
application.registerUserNotificationSettings(notificationSettings)
return true
}
func applicationWillResignActive(application: UIApplication) {
}
func applicationDidEnterBackground(application: UIApplication) {
}
func applicationWillEnterForeground(application: UIApplication) {
}
func applicationDidBecomeActive(application: UIApplication) {
}
func applicationWillTerminate(application: UIApplication) {
}
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject],
fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
print("MessageID : \(userInfo["gcm_message_id"]!)")
print("%#", userInfo)
}
}
There are a few more things you need to do. When you registerForRemoteNotifications, you receive an APNS Token which you need to give to Firebase. This is done in application didRegisterForRemoteNotificationsWithDeviceToken.
import UIKit
import CoreData
import Firebase
import FirebaseMessaging
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
override init() {
super.init()
FIRApp.configure()
}
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
application.registerForRemoteNotifications()
application.registerUserNotificationSettings(
UIUserNotificationSettings(
forTypes: [.Alert, .Badge, .Sound],
categories: nil
)
)
NSNotificationCenter.defaultCenter().addObserver(self,
selector: #selector(tokenRefreshNotification),
name: kFIRInstanceIDTokenRefreshNotification,
object: nil
)
return true
}
func applicationDidEnterBackground(application: UIApplication) {
FIRMessaging.messaging().disconnect()
}
func applicationDidBecomeActive(application: UIApplication) {
FIRMessaging.messaging().connectWithCompletion { (error) in
switch error {
case .Some:
print("Unable to connect with FCM. \(error)")
case .None:
print("Connected to FCM.")
}
}
}
func applicationWillResignActive(application: UIApplication) {}
func applicationWillEnterForeground(application: UIApplication) {}
func applicationWillTerminate(application: UIApplication) {}
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: .Sandbox)
}
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject],
fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
print("MessageID : \(userInfo["gcm.message_id"]!)")
print("%#", userInfo)
}
func tokenRefreshNotification(notification: NSNotification) {
if let refreshedToken = FIRInstanceID.instanceID().token() {
print("Instance ID token: \(refreshedToken)")
}
applicationDidBecomeActive(UIApplication.sharedApplication())
}
}

Resources