UserNotifications related events - ios

I am working with an iOS app using UserNotifications.
When the user taps on a notification, this method is fired:
userNotificationCenter(_:didReceive:withCompletionHandler:)
I want to know if there is a method called when the notification arrives, independently of when the user reacts.

Yes you can : https://developer.apple.com/documentation/usernotifications/unusernotificationcenterdelegate/1649518-usernotificationcenter
Of course the app has to be open for that. you can not execute code if the app is closed.
In some cases you can execute code if the app is in background but that required special authorisation.

Related

Automatically performing task when user notification is delivered in Swift 5

I want to perform a simple task in my app when a local user notification is triggered while the app is not in the foreground. Can I do this?
I can't use UNNotificationAction, because I don't want to rely on the user to do anything. And it seems I can't use UNUserNotificationCenterDelegate because it only has a method to handle notifications while the app is in foreground.
I have came to conclusion that what I asked is not possible. Here is my alternative solution: I wanted to perform an action within my app when a location based user notification was fired. To accomplish what I needed, I set up the monitoring for my CLCircularRegion. The delegate for CLLocationManager launches the app in the background upon entry to the region, and I can do what I want inside delegate method.

Ignore push notifications when iOS app is in the foreground

I have a fairly large iOS project. When the app receives a notifications while in the foreground, the notification is displayed in something that looks like an AlertView. I want to get rid of it. I have no idea if this is something I programmed myself a long time ago, or if one of the frameworks in the project (Parse, Onesignal, FBSDK) is doing this. My question is, how can I find out where that alert view is coming from, so I can remove that code. I have not implemented the willPresentNotification method anywhere (I have searched through the entire project). I do have a didReceiveRemoteNotification method, and even though that should only be called when a notification is tapped, I have tried commenting it out. I have also searched through the entire project for UIAlertView and UIAlertController, to no avail.
OneSignal SDK automatically uses the new UserNotifications Framework, when iOS10 is detected on device.
In this case, the AppDelegate method didReceiveRemoteNotification method not get called, instead methods in UNUserNotificationCenterDelegate get invoked, which is captured by SDK to record clicks/views.
OneSignal use callback to handle received Notification.
OSHandleNotificationReceivedBlock: Called when the app receives a notification while in focus only
OSHandleNotificationActionBlock: Called when the user opens or taps an action on a notification.
OSNotificationOpenedResult: The information returned from a notification the user received.
You can directly implement UNUserNotificationCenterDelegate methods to handling notification-related interactions in your app.

Push notifications not working properly when the app is not active (killed)

I'm facing a problem with push notifications, I'm using Google Cloud Messaging,
My problem is that my app works with some cached data, and I refresh that cache with the data coming from push notificacions, so when the app is killed by the user (home button + swipe-up) and the app receive a push notification it doesn't call the method didReceiveRemoteNotification, so the app can't access to the payload of that notification and update the cached data.
So, is there a way to achieve this?
Only when the user taps the notifications and the app gets it through the application:didFinishLaunchingWithOptions method?
If the user opens the app by clicking the application icon I can't get the notificaton's payload?
PD: If the app is in foreground or background (not killed) it works perfectly
If you wish your app to receive the push notification even when it is killed, add the key "content-available":"1" to the push payload.
Look here
EDIT:
After digging some more, I found out that silent push (e.g content-available:1), does not wake the app if it was killed by the user:
However, the system does not automatically launch your app if the user has force-quit it
I must say, I can't really understand why the OS does not let my app wake up when silent push arrives when it's dead. What's the point then???
This is the expected behavior. didReceiveRemoteNotification will not be called if the user killed the app, unless your app has VoIP permissions.
In case of killed application. both application:didFinishLaunchingWithOptionsandapplication:didReceiveRemoteNotification:fetchCompletionHandler:are called. In the prior one. The key of notification either remote or local is passed in options parameter. And the later one is called in only case when remote notification. The process is explained in detail in Apple Docs Here. The snapshot is pasted here as well.
Handling an Actionable Notification
If your app is not running in the foreground, to handle the default action when a user just swipes or taps on a notification, iOS launches your app in the foreground and calls the UIApplicationDelegate method application:didFinishLaunchingWithOptions: passing in the local notification or the remote notification in the options dictionary. In the remote notification case, the system also calls application:didReceiveRemoteNotification:fetchCompletionHandler:.
If your app is already in the foreground, iOS does not show the notification. Instead, to handle the default action, it calls one of the UIApplicationDelegate methods application:didReceiveLocalNotification: or application:didReceiveRemoteNotification:fetchCompletionHandler:. (If you don’t implement application:didReceiveRemoteNotification:fetchCompletionHandler:, iOS calls application:didReceiveRemoteNotification:.)
Finally, to handle the custom actions available in iOS 8 or newer , you need to implement at least one of two new methods on your app delegate, application:handleActionWithIdentifier:forRemoteNotification:completionHandler: or application:handleActionWithIdentifier:forLocalNotification:completionHandler:. In either case, you receive the action identifier, which you can use to determine what action was tapped. You also receive the notification, remote or local, which you can use to retrieve any information you need to handle that action. Finally, the system passes you the completion handler, which you must call when you finish handling the action. Listing 2-8 shows an example implementation that calls a self-defined action handler method. Reference Apple Docs
Edit:
The user taps the default button in the alert or taps (or clicks) the app icon. If the default action button is tapped (on a device running iOS), the system launches the app and the app calls its delegate’s application:didFinishLaunchingWithOptions: method, passing in the notification payload (for remote notifications) or the local-notification object (for local notifications). Although application:didFinishLaunchingWithOptions: isn’t the best place to handle the notification, getting the payload at this point gives you the opportunity to start the update process before your handler method is called.
Reference: Apple Docs
When the app is killed and the push notification triggered contains some actionable button. When we click on a Action Button of Push Notification then:
The first delegate that is executed is:
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
But in here the launchOptions are nil.
The second delegate that is executed is:
-(void)application:(UIApplication *)application handleActionWithIdentifier:(nullable NSString *)identifier forRemoteNotification:(nonnull NSDictionary *)userInfo completionHandler:(nonnull void (^)())completionHandler
In this the variable userInfo contains all the payload of the Push Notification. With the help of identifier we can identify which action was invoked and then perform our respective operations.
add target of notification service extension in your project it contains two methods upper one method call in killed time and add a key "mutable_content" : true in server side of your notification payload

Silent notification - ios

I'm building an app and I have created a method to detect if the user has new pictures in his photo librery throw ALAssetsLibrary, the method works fine.
I want to run this method from time to time to check for new pictures. If the user has new pictures, to notify him by a notificaiton.
I'm searching for a trigger to activate this method from time to time while the app is in background state or not running at all.
I know by sending a silent notification in ios 7, I can activate the app on the background state.
Once a silent notification is received , can I activate the method somehow? or the silent notoficaiton is just for receiving data and update the app.
Do you think of any other way that I can activate this function without the user will know about it ?
Not Possible currently!
1- When a silent notification is received the app is only intended to upload/download data hence we can only work with NSURLSessionTask. Access to other API's which require asynchronous blocks to execute like ALAssetLibrary is not available.
2- No other option of scanning library without the user knowing. You can display a notification to User and then on User's discretion app can be launched to perform desired scanning.

Handling remote notification while app is totally off by launching from app icon

I might by fighting the windmills but I need to put some clearance into my knowledge of remote notifications. I want to handle notification while my app is turned off (killed from the app switcher) but user decides to turn it on not by tapping on notification but by tapping on app icon.
As far is I know, when app is killed and a remote notification arrives user has to tap on notification to pass it in launchOptions from didFinishLaunchingWithOptions: but... I want to handle this notification when user taps on app icon and nothing is passed to lauchOptions. In that scenario, at the moment I have no notification at all...
Is it possible to handle notification in background and perform action on it no matter how the app has been launched? Maybe didReceiveRemoteNotification: fetchCompletionHandler:?
Yeah, you are fighting the windmills :)
I recommend you to read Local and Push Notifications in depth. It's a bit long but the doc is clarifying.
In a fragment of this doc you can read:
If the application icon is tapped on a device running iOS, the
application calls the same method
(application:didFinishLaunchingWithOptions:), but furnishes no
information about the notification.
And later on:
When handling remote notifications in
application:didFinishLaunchingWithOptions: or
applicationDidFinishLaunching:, the application delegate might perform
a major additional task. Just after the application launches, the
delegate should connect with its provider and fetch the waiting data.
Listing 2-5 gives a schematic illustration of this procedure.
So having said this you could have a list of sent notifications for each device in your server and each time your app launches check if the device has any pending notification.
From the Local and Push Notification Programming Guide
As a result of the presented notification, the user taps the action button of the alert or taps (or clicks) the application icon.
If the action button is tapped (on a device running iOS), the system launches the application and the application calls its delegate’s application:didFinishLaunchingWithOptions: method (if implemented); it passes in the notification payload (for remote notifications) or the local-notification object (for local notifications).
If the application icon is tapped on a device running iOS, the application calls the same method, but furnishes no information about the notification
So, if your application is launched from the icon then you won't receive the notification data. You need your app to query the service/data store that is responsible for sending the notification to see if there is outstanding data/transactions/whatever.

Resources