iOS 10 UNNotificationAction, can move from background to foreground mode? - ios

UINotificationAction is defined as below
let customAction = UNNotificationAction(identifier: "customCategory.Action", title: "Do something", options: [])
On click, this will make a web service request to fetch data using UNUserNotificationCenterDelegate method as below
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
let actionIdentifier = response.actionIdentifier
switch actionIdentifier {
case customCategory.Action:
if authTokenNotExpired {
// Make service call
} else {
// Show login screen (In foreground)
}
}
completionHandler()
}
But the application has login and when auth token expires, the web service request fails.
As per requirement, in this failure scenario, the login screen should be displayed.
Is it possible to move the application from background mode to foreground in order to display login screen?

Your question is different from what you want.. In order to have like this..
1 solution is to do like this in appdelegate:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
NotificationCenter.default.addObserver(self, selector: #selector(triggerGetNewToken(note:)), name: .isNeedNewToken, object: nil)
}
#objc func triggerGetNewToken(note:NSNotification){
debugLog(logMessage: "GETTING NEW TOKENS NOW IN APPDELEGATE!")
api_token.param(serverKey: appkey)
}

Related

How to check if an iOS app was opened with a push notification (and the data of that notification)?

I can't find any documentation on how to handle this, I'm sending a push notification using firebase messaging with a data payload, title and message. The notification comes through fine but opening the app from background does't trigger any specific options here:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { FirebaseApp.configure();
// Override point for customization after application launch.
return true
}
The function doesn't seem to be called.
This is the function called for push notification presses
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
let application = UIApplication.shared
if(application.applicationState == .active){
//Prints the message when user tapped the notification bar when the app is in foreground
print(userInfo)
}
if(application.applicationState == .inactive)
{
print("user tapped the notification bar when the app is in background")
}
completionHandler()
}

userNotificationCenter(_:didReceive:withCompletionHandler:) isn't called

The app is closed. I tap the remote notification banner to launch the app, the userNotificationCenter(_:didReceive:withCompletionHandler:) method should be called.
My app works correctly on the build version, but failed on TestFlight version.
How can I fix this situation?
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
printD(userInfo)
}
As Apple Document about userNotificationCenter(_:didReceive:withCompletionHandler:)
Asks the delegate how to handle a notification that arrived while the
app was running in the foreground.
So when app closed, your app didn't call userNotificationCenter function
Try to catch notification in this case by below code:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
if launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification] != nil {
// Do your task here
}
}

Not receiving remote push notifications on iOS

I'm currently rewriting my app from Objective-C to Swift and working on notifications. For some reason Swift version of the app is not receiving any remote push notifications while Objective-C version does.
Here's the code I'm using to register for notifications in AppDelegate:
UNUserNotificationCenter.current().delegate = self
let options: UNAuthorizationOptions = [.badge, .alert, .sound]
UNUserNotificationCenter.current().requestAuthorization(options: options, completionHandler: { granted, error in
print("access granted: \(granted)")
})
application.registerForRemoteNotifications()
I assume that the app successfully registers because didRegisterForRemoteNotificationsWithDeviceToken method gets called. But when I try to send the test notification using the token I got from that method, I don't get actual notification on device.
Also none of these methods get called:
func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType) {
}
func userNotificationCenter(_ center: UNUserNotificationCenter, openSettingsFor notification: UNNotification?) {
}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (_ options: UNNotificationPresentationOptions) -> Void) {
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
}
func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, forRemoteNotification userInfo: [AnyHashable : Any], completionHandler: #escaping () -> Void) {
}
What am I doing wrong?
you say that you are not receiving so let's first make sure that those methods you mention before that are not being called are comming from here extension AppDelegate: UNUserNotificationCenterDelegate (By the way when you do implement the didReceive method make sure you call the completionHandler() at the end)
When you do this:
application.registerForRemoteNotifications()
Make sure to run it from the main thread, as it can be called if not specified from the background and that might fail. You can do so by doing
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
I'll assume that you are getting the device token this way or something similar:
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
// 1. Convert device token to string
let tokenParts = deviceToken.map { data -> String in
return String(format: "%02.2hhx", data)
}
let token = tokenParts.joined()
// 2. Print device token to use for PNs payloads
print("Device Token: \(token)")
}
Finally implement this method to see if there are any errors while registering the device
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
// 1. Print out error if PNs registration not successful
print("Failed to register for remote notifications with error: \(error)")
}
Oh by the way (just in case you have missed it) make sure you enabled in your project's target the push notification.
Make sure you have enabled Push notification in your project setting capabilities.
How to enable:
go to target: -> select project -> go to capabilities -> go to Push Notification. enable it there.
Another thing is the certificate. While development you should not Production certificates.

How to get userInfo when user click in notification when app is closed?

I'm doing an app that schedule local notifications and save an userInfo. That's part its ok.
But when app is closed, Notification appear, but when user click, the method is not called and I can't handle userInfo.
I saw that there's a new way to receive notification with UNUserNotificationCenter. But is not working too.
That's my implementation in AppDelegate:
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
let lNotification = UILocalNotification()
lNotification.userInfo = response.notification.request.content.userInfo
applicationWorker.manage(localNotification: lNotification)
}
Anyone to help me? I saw all the questions related here and didn't found anything.
Thanks!
EDIT:
If someone are looking for a solution, I added UNUserNotificationCenter.current().delegate = self in didFinishLaunchingWithOptions and it worked.
From iOS 10 onwards, the method you mention should be called whether app is opening from background or inactive state. Perhaps you are not accessing the userInfo correctly. The example below works for me.
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
if let yourData = userInfo["yourKey"] as? String {
// Handle your data here, pass it to a view controller etc.
}
}
Edit: as per the edit to the question, the notification centre delegate must be set in the didFinishLaunching() method, or the method above will not get called.
UNUserNotificationCenter.current().delegate = self
You can got the notification user info from launch option when application open from notification. Here is the code
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
if let notification = launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification] as? [String: AnyObject] {
if let aps = notification["aps"] as? NSDictionary
{
}
}
}

Notification iOs Push delivered?

I recently set up notifications on my application, I can send via php and no worries, everything works fine.
Since last week, I am trying to find out if a push notification is received by the phone or not..
I can know when someone clicks on it but if the person does not click on it and prefer to open the application, it does not work..
Is there not a simple function that can tell me if a notification has just been received by the application ?
In my AppDelegate.swift :
import UIKit
import UserNotifications
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
...
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Check if launched from notification
if let notification = launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification] as? [String: AnyObject] {
//print(notification)
window?.rootViewController?.present(ViewController(), animated: true, completion: nil)
}
else{
//print("ici ?")
registerForRemoteNotification()
}
return true
}
...
//Called when a notification is delivered to a foreground app.
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.alert, .badge, .sound])
}
//Called to let your app know which action was selected by the user for a given notification.
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
completionHandler()
}
...
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
**print("here ?")**
switch((application.applicationState)){
case UIApplicationState.inactive:
print("Inactive")
//Show the view with the content of the push
completionHandler(.newData)
case UIApplicationState.background:
print("Background")
//Refresh the local model
completionHandler(.newData)
default:
print("Active")
//Show an in-app banner
completionHandler(.newData)
break
}
}
}
Problem : I never pass in didReceiveRemoteNotification :/
The "print here" is never displayed.
I have a mistake on this line :
Instance method
'application(application:didReceiveRemoteNotification:fetchCompletionHandler:)'
nearly matches optional requirement
'application(_:didReceiveRemoteNotification:fetchCompletionHandler:)'
of protocol 'UIApplicationDelegate'
But I do not understand :/
Do you have an idea ?
Thx for your help ^^
It's rather common mistake since the conversion to Swift 3 - you're using Swift 2 method.
The right signature of this method in Swift 3 is:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
print("here?")
}

Resources