Push notifivations stop to work after few minutes - ios

I have very strange behavior of APNS in my app. All my certificates, profiles etc is configured correctly and I actually can receive push notifications if I run my app first time on the device. But after few minutes they stop to come.
If I delete my app from device and run again from project, notifications come but only during short time. Then I have to delete it again, install again and so on...
I'm very wondering with this proplem. As I know there is no limitation to send push notifications and device token does not have expiration date (even if has,
few minutes are too short).
I have this first time and have no idea what a reason it can be...

Looks like you have called the fetching notifications methods not from
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
This is one method of App Delegate which will always be called when your application launches,
Check out the descriptions of these methods. Hope this helps.

Related

When in iOS applicationDidEnterBackground called immediately after applicationDidBecomeActive?

in our app we are logging (with an external analytics service) every time the user open our app.
However, we have noticed that there are many weird app sessions (almost 15% of total sessions).
Following the device timestamp of the events, the following methods are called:
application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?)
applicationDidBecomeActive(_ application: UIApplication)
viewDidAppear(_ animated: Bool) // App Splash Screen
applicationDidEnterBackground(_ application: UIApplication)
Looking at the timestamp, from didFinishLaunchingWithOptions to applicationDidEnterBackground there is just a very short delay (<1 sec).
Our hypothesis is that the system sometimes wakes up the app without it being actually opened and "seen" by the user. But we can't find any docs about this kind of use case, and we can't reproduce ourself the issue.
Did someone have experienced something similar?
EDIT:
I want to add that these suspicious sessions are often (but not always) linked to an app update.
I'm not sure...
I suppose if app wasn't user terminated nor suspended but was just put out of memory because other apps needed the memory, then almost a launch options can wake the app up if needed. Some examples:
geofence
interaction with push notification's actions. Example if you have userNotificationCenter(_:didReceive:withCompletionHandler:) implemented...
silent notification
background app refresh
Take a look at here and see what launch options are possible for your app. I'm not sure if all of them can actually launch the app or what...
If you want more visibility into this, then make sure for future you log the launchoptionskey that caused the app to get launched...
You need more info - I would extend your logging to dump the launchOptions dictionary in
application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?)
Looking at UIApplication.LaunchOptionsKey, there are a lot of options which may be involved. Note, as the help says: The contents of this dictionary may be empty in situations where the user launched the app directly
if let lop = launchOptions {
let toLog = lop.map{"\($0.0.rawValue) \($0.1)"}.joined(separator:"\n")
// log the options
...}
I did have an idea this might be related to previewing in AppSwitcher but that doesn't seem to trigger didFinishLaunchingWithOptions, unless you actually bring the app to the front. Maybe some split-screen stuff on iPad? It feels like the app is being invoked in a context where it can't get past the launch screen.

Send request to web service when app gets killed? (Swift 3)

It's very important for my app to be notified every time the user kills my app (not moving it to the background, but actually quitting it altogether by double-tapping the Home button and swiping my app screenshot up). I know applicationWillTerminate() barely ever gets called, so I was wondering what the safest way is to be notified when a user will kill the app. It seems very unlikely that Apple hasn't provided ANY form of solution for this, as a lot of iOS users make it a custom to kill apps when they're done using it, so it would be really really REALLY weird if it would be impossible to catch this event. The only thing I need to do is fire off a URLRequest to send some updating instructions to my web service.
I get more consistency when I add an observer to handle UIApplicationWillTerminateNotification. It gets called when the user double-taps the Home button and swipe the app to kill it.
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
{
NSNotificationCenter.defaultCenter().addObserver(self, selector:#selector(AppDelegate.onAppWillTerminate(_:)), name:UIApplicationWillTerminateNotification, object:nil)
return true
}
func onAppWillTerminate(notification:NSNotification)
{
print("onAppWillTerminate")
}

iOS Handle Push notifications on application startup only when UI is ready

When the application is not running, and a notification is received, it will arrive inside:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
I have a log there and all is fine, however, let's say I want to show an alert with the body of the notification?
My alert code uses window!.rootViewController?.presentViewController(), however inside didFinishLaunchingWithOptions the UI has not loaded yet, and there is not view controller yet.
What is the best practice to trigger UI events in this scenario?
You have different options on the base of your architecture and view controllers flow. For example you can have a kind of NotificationManager, a singleton which has the responsibility to store information about any push notification received.
In your didFinishLaunchingWithOptions you can set the notification in such manager; afterwards the first view controller you present could interrogate such manager and decide whether there is any notification to consume or continue with the normal flow.
Hope it helps.

How to get the proper UINotification when selected on locked screen

Here is my scenario:
The app receives some notifications, in order to be able to have actions on my locked screen they are in silent mode (content-available = 1 on aps payload).
In didReceiveRemoteNotification callback I save it to core data (background or foreground).
My problem is:
Assuming the app was already running and I have locked the screen, when I tap on some notification no callback is called. So far I'm not able to find the proper callback that handles this event.
Am I missing something?
I need to have the notification list saved and be able to go to the proper view when some notification arrives (and is tapped).
By the way receiving the notification, saving, going to the proper view ... everything works except when the screen is locked.
I suspect if your app was running when notification came because if application is in inactive state and notification is tapped then didReceiveRemoteNotification is called by iOS.
However, if for some reason, application is not running then didReceiveRemoteNotification function is not called. In such cases, if user click notification, app is launched by notification and didFinishLaunchingWithOptions gets called:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
var userinfo : NSDictionary = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];
print(launchOptions);
return true
}
Please check once in your didFinishLaunchingWithOptions function.

How to know a push message info if app is launched from background directly rather than from notification msg?

I have properly registered for the push notification.
Implemented following method to receive notification.
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject])
Also used UIApplicationLaunchOptionsRemoteNotificationKey from func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool.
I'm able to receive notification when the app is active. I'm also able to see the notification if I open the app from the notification by selecting it from banner or alert.
But if app is not active, it could be alive or killed and if a notification arrives at that point. And I ignore the notification and open the app by directly selecting the app icon from the home screen, I'm not getting the notification information in the UIApplicationLaunchOptionsRemoteNotificationKey from func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool.
So what is the right way to handle this scenario? Should the app call server and get the recent messages it sent? Any help is much appreciated.
If the user will open you app directly from it's home screen, you would not get access to the push notification dictionary.
If you need the data sent in the push notification, so the proper way will be a server request as you suggested.
If user enter the app by click the icon or launch from the background, the push notification message can't deliver to you, the message is cached by system, the only way to get it is from notification center
Answering my question:
It is possible for the app in the background to receive push notification.
To do so send content-available in the aps dictionary of push notification.
Enable background mode of the app from the Background modes section of the Capabilities tab in your Xcode project.
Implement application:didReceiveRemoteNotification:fetchCompletionHandler: in the app delegate.
References:
See section 'Notification Payload' in https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html
See section 'Using Push Notifications to Initiate a Download' in
https://developer.apple.com/library/prerelease/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html
However if app is killed then the appdelegate's application:didReceiveRemoteNotification:fetchCompletionHandler: is not getting called.
According to Will iOS launch my app into the background if it was force-quit by the user? post on iOS8.0 it is possible to do it using PushKit. But I have not tested it. And also if VOIP is not used then I dont know if it is possible for app to receive push notification information if it is killed.

Resources