ios 9 push notification not showing while app is open - ios

if (deviceToken == nil) {
print("There is no deviceToken saved yet.")
let settings = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
UIApplication.sharedApplication().registerUserNotificationSettings(settings)
UIApplication.sharedApplication().registerForRemoteNotifications()
}
This my code for permission.

If your app is already open, no notification is shown but the application is responsible for updating the user interface or downloading new content.
Implement application(_:didReceiveRemoteNotification:fetchCompletionHandler:)
to handle the notification, as described in the documentation. here, you could create an alert that shows a title and message similar to the banner you'll see when receiving a standard notification.

Need to add the completionHandler part, otherwise push notification is received. but it will be not shown.
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (_ options: UNNotificationPresentationOptions) -> Void) {
completionHandler([.alert, .badge, .sound])
}

For showing alert view while running application you have to use:
func application(_ application: UIApplication,
didReceiveRemoteNotification userInfo: [NSObject : AnyObject])
Notification payload is in the userInfo variable. You have to decide what to do with it, how to show it etc.
Docs say:
When the operating system delivers a local notification or remote
notification and the target app is not running in the foreground, it
can present the notification to the user through an alert, icon badge
number, or sound. If there is a notification alert and the user taps
or clicks an action button (or moves the action slider), the app
launches and calls a method to pass in the local-notification object
or remote-notification payload. If the app is running in the
foreground when the notification is delivered, the app delegate
receives a local or remote notification.
This means, when the app is running and receives a notification, no system alert is shown.

Related

iOS app loads buggy when launching from a remote notification

My iOS app launches buggy (no launch image, safe areas aren't observed, tab bar doesn't show, etc.) when it's opened from a remote notification (when the user taps a push notification to open the app from a terminated state). I don't want the push notification to have any special functionality at all, I want it as plain as possible.
This is how I have my notifications configured in the App Delegate:
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
setupUserNotifications()
return true
}
private func setupUserNotifications() {
let notifications = UNUserNotificationCenter.current()
let connectionMessages = UNNotificationCategory(identifier: "connectionMessageNotification",
actions: [],
intentIdentifiers: [],
options: UNNotificationCategoryOptions.init())
let interactionMessages = UNNotificationCategory(identifier: "interactionMessageNotification",
actions: [],
intentIdentifiers: [],
options: UNNotificationCategoryOptions.init())
notifications.delegate = self
notifications.setNotificationCategories([connectionMessages, interactionMessages])
notifications.requestAuthorization(options: [.alert, .sound, .badge]) { (granted, error) in
if granted {
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
} else {
print(if: error)
}
}
}
And this is how I handle the delegate (doing nothing and just calling completion):
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void) {
print("did tap remote notification")
completionHandler()
}
Is there a step I'm missing? Am I supposed to implement application(_:willFinishLaunchingWithOptions:)? What I don't understand is that if the user launches the app by tapping a push notification, shouldn't the app just launch normally without having to take any extra steps?
The problem was that my app was configured to receive background push notifications and it would launch the app in the background (before the user tapped on the notification) and so when the user did tap on the notification to launch the app it would sometimes, I guess, catch it in some intermediate state and the UI would look all funky. I assume that there are extra steps that one would need to take to handle launching the app through a background notification. Regardless, by disabling background notifications, the app now launches when the user taps on the push notification as normal. Whew.

iOS how to set Alarm and schedule work/notifications

Hi I am new to iOS basically I am android developer. But Right now I am working on iOS app,It is simply an iOS replica of android. Let me tell you about what I want in app:
Our app features alarm, that will remind our client that on a specific date you have this meeting. For example, if user sets alarm for 1-jan-2019 at time 9:00AM then on that day and time user must be notified of this meeting.
I have read alot and found that in iOS we can not do this since when app is in background it can not run code of his own? So I have 2 basic questions:
What I want:
First of all how to schedule an Alarm
If alarm is set and app is in background/terminated then how to generate notification and when user click on notification take him to specific view?
If app is in forground then how to take him to wanted view? also if app is on specific view how to update view itself when alarm goes on?
I know these are 3 main and major part that required too much coding. But I just want directions. Give me link of chunks of code. I am using xcode 9.2 and swift 4.0. Thanks in advance ...
You many have to schedule local notification which is now available in UNUserNotificationCenter.
So,
For Scheduling a Notification Locally from Your App, follow this doc.
For Handling Notifications and Notification-Related Actions, follow this doc.
To Handle Notifications in your AppDelegate or where you want to handle UNUserNotificationCenter delegate method, add below code:
class AppDelegate:NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate{
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
let center = UNUserNotificationCenter.current()
center.delegate = self // Don't forgot to set delegate
//To get permissions from user:
let options: UNAuthorizationOptions = [.alert, .sound, .badge];
center.requestAuthorization(options: options) {
(granted, error) in
if !granted {
print("Something went wrong")
}
}
return true
}
}
You can use local notifications for getting an alarm notifications.
You can handle the click in the delegate method of UNUserNotificationCenterDelegate and navigate to the desired page.
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void)
For displaying notification when app is in foreground use this method from same delegate
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void)

APNS Silent Remote Notification not triggering - SWIFT 3

Scenarios:
1) Silent or Normal payload when App's in Foreground:
Nothing happens
2) Silent payload when App's in Background:
Nothing happens
3) Normal payload when App's in Background:
If User click the notification to open the App.
triggers the application:didReceiveRemoteNotification:fetchCompletionHandler
If user open the App clicking the App icon:
Nothing happens
These are the payloads I'm using for the APNs:
Normal payload: .
{
"aps":{
"alert":"andre test",
"badge":0,
"sound":"default",
"content-available":1
},
"acme-syncalarm":"true"
}
Silent payload: .
{
"aps":{
"content-available":1
},
"acme-syncalarm":"true"
}
I've implemented the Remote Push Notification using this code:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
print("Receeeeeeeeived: \(userInfo)")
UIApplication.shared.applicationIconBadgeNumber = 11
completionHandler(.newData)
}
I also implemented this to check if the App is recovering from a kill state (as I've read in some Questions too), but the code never enters the print(rn)line.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
if let rn = launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification] {
print(rn)
}
}
EDIT 1 -
I have also enabled Remote Notifications in background mode for the App.
What do I have to do to cover the "Nothing Happens" Scenarios? 1 , 2 and 3.2 ?
Some notes:
"If user open the App clicking the App icon: Nothing happens" <-- That's expected, because you didn't interact with any notification directly. Imagine if you had 5 notifications arrived. How would you know which notification you should process...
normal payload won't have any key named content-available. So that again is a silent notification. Can you first see my answer here?
Some suggestions:
Make sure you've enabled Remote Notifications in background mode. Like this:
Additionally See here. iOS 11 initial releases were buggy for silent notifications. Make sure you have the latest version for your testing, otherwise it won't work. If you have an iOS 10 device, then first try testing with that...
Make sure you have Background App refresh and notifications available on your device. To see how to do it, refer to my linked answer.
Are you creating the payload yourself or you're using FireBase? If you're using Firebase then some of the keys change...and you must adjust accordingly.
make sure you've set some object as the delegate of UNUserNotificationCenterDelegate e.g.:
UNUserNotificationCenter.current().delegate = delegateObject
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
let content = notification.request.content
// Process notification content
completionHandler([.alert, .sound, .badge]) // Display notification as regular alert and play sound
}
Code copied from here.
If you don't do such then you won't be showing any notification when the app is in the foreground. This should resolve the issue of when app is in foreground and you've received a normal remote notification.

In which method should I handle iOS remote notification?

I know similar questions have been asked many times. But it is still very confusing to me after reading those threads, especially after UNUserNotificationCenter is introduced in iOS 10.
The official documentation mentioned 3 methods where I can handle remote notifications:
Implement userNotificationCenter:willPresentNotification:withCompletionHandler: to handle a notification when the app is in foreground.
Implement userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler: when the app is in background or not running.
But the documentation also mentioned: In iOS and tvOS, the system delivers the notification payload to the application:didReceiveRemoteNotification:fetchCompletionHandler: method of the app delegate.
So,
To handle a remote notification when app is in background/inactive, should I put my code in application delegate method in 3, or the notificationCenter delegate in 2? Since UNUserNotificationCenter is only available for iOS>10, should I write different code to handle each case?
About 1, it is only available after iOS 10. How can I handle remote notifications when app is running in foreground before iOS 10?
And, more confusing: In case the app is in background, when are the delegate methods called: when the notification message is received? or when the user taps the notification?
Related: iOS push notification: how to detect if the user tapped on notification when the app is in background?
iOS 10 and later:
1) userNotificationCenter willPresent notification: Generally used to decide what to do when user is already inside the app and a notification arrives. You could possibly trigger a remote notification inside the app. After the user taps on the remote notification, method 2 (didReceive response) gets called.
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (_ options: UNNotificationPresentationOptions) -> Void) {
//Handle push from foreground
//When a notification arrives and your user is using the app, you can maybe notify user by showing a remote notification by doing this
completionHandler([.alert, .badge, .sound])
//To print notification payload:
print(notification.request.content.userInfo)
}
2) userNotificationCenter didReceive response: Generally used to redirect the user to a particular screen of the app after user taps on the notification.
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
//Handle push from background or closed (or even in foreground)
//This method is called when user taps on a notification
//To print notification payload:
print(response.notification.request.content.userInfo)
}
Below iOS 10:
3) application didReceiveRemoteNotification:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
//To print notification payload
print(userInfo)
if #available(iOS 10.0, *) {
}
else {
//Handle remote notifications for devices below iOS 10
if application.applicationState == .active {
//app is currently in foreground
}
else if application.applicationState == .background {
//app is in background
}
else if application.applicationState == .inactive {
//app is transitioning from background to foreground (user taps notification)
}
}
}
4) application didFinishLaunchingWithOptions launchOptions: The only scenario which is left for devices below iOS 10 is when app is closed and user taps on the notification launching the app. You'll have to check the following method for this scenario.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
//To print notification payload:
if let notification = launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification] as? [AnyHashable: Any] {
print(notification)
}
}
LaunchOptions is a dictionary indicating the reason the app was
launched (if any). The contents of this dictionary may be empty in
situations where the user launched the app directly.
Now to answer your questions,
To handle a remote notification when app is in background/inactive, you'll have to add your code in method 2 (userNotificationCenter didReceive response) for devices with iOS 10 and above. Also, you'll have to use method 3 (application didReceiveRemoteNotification) for devices below iOS 10.
To handle remote notifications when app is running in foreground before iOS 10, use the method 3 active state.
In addition to the great answer by Ameya, I wanted to point out that userNotificationCenter:willPresent:notification does not get called if app is in background state.
My complete solution to handle all cases on iOS 10+ would be to also use application:didFinishLaunchingWithOptions:launchOptions, and check if in background state, and handle the notification there too. Your payload, however, now also needs to include the "content-available": 1 field).

Reloading the push notification badge in the background

I am creating a notification service using swift3 in xcode 10.
The problem now is that when a push notification comes in the background (even when the app is closed), the badge does not increase at first, but increases by 1 from the second push notification.
Furthermore, when I enter the app and come back in the background, the number of badges will be normal, but the above problem will happen again.
I tried to check the problem through delay or local notifications, but I have not been able to figure out what the problem is.
Below are the notifications related to the notifications within the AppDelegate. Push Notification Click event also works normally.
class AppDelegate: UIResponder, UIApplicationDelegate, GIDSignInDelegate, NaverThirdPartyLoginConnectionDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions:[UIApplicationLaunchOptionsKey: Any]?) -> Bool {
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().requestAuthorization(options: [.badge, .sound, .alert,], completionHandler: {(granted, error) in
if (granted)
{
application.registerForRemoteNotifications()
}
else{
}
})
return true
}
...
...
extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.badge, .alert, .sound])
UIApplication.shared.applicationIconBadgeNumber = UIApplication.shared.applicationIconBadgeNumber + 1
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
print("userInfo: \(response.notification.request.content.userInfo)")
var userInfo:[AnyHashable: Any]?
let pushId:Int32 = userInfo?["uid"] as! Int32
self.moveView(pushId)// My app load method
}
}
Running app in the background state is just a brief stop on the way to the app being suspended. While suspended, an app remains in memory but does not execute any code. For this reason your code is not executing and thus badge value does not update. See these below link to about application state and background execution.
Application State
Background Execution
So better approach to solve this problem is to send send badge value inside of push notification payload. e.g
{
"aps" : {
"alert" : {
"title" : "Game Request",
"body" : "Bob wants to play poker",
"action-loc-key" : "PLAY"
},
"badge" : 5
},
"acme1" : "bar",
"acme2" : [ "bang", "whiz" ]
}
See this link to create remote notification payload
Creating the Notification Payload
Don't increase badge value programmatically unless you need to show badge for local notification. If you want to execute code on background while push notification receive, use VoIP push notification which has few restriction e.g app must be related VoIP services.
I recommend to change the push notification payload.
Thanks.

Resources