How to create background services for local notification? - ios

I am trying to create local notifications for my iOS application based on JSON new data.
I have created web services and parsing some datas and store into plist as a string at first time.
I want to parse JSON at every n minutes once and compare with plist stored data for anything newly arrived datas or not.
If anything newly arrived I want to show notification.
Those process want to do application active and background both times without any hanging.
Thanks,

iOS does not support these kind of background service. The reason being that they drain the battery and therefor give the user a bad experience. You might want to implement it serverside.
Apple only allows background running for apps that fall the in following categories: VOIP, audio streaming, location and accessory (bluetooth).

If you want to update data from the server in the background, you basically have 2 options:
Use background fetch. The system will launch your app into the background in specific intervals (which are not entirely under your control!) and give it the chance to download (have a look at this post for a good intro).
Use (silent) push notifications. This of course requires work on the backend-side.
Which one you should use depends on things like
Whether you have control over the backend (if not, you can't send push notifications)
How often the data is updated. If it's updated very often, background fetch might be ok. If it's updated very infrequently or irregularly, then push might be superior.

You can use Silent Push Notifications,if Push notification serve your purpose.It doesn't come in notification tray.
1.As soon as when notification comes , Below method is called,overide this method
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
completionHandler(UIBackgroundFetchResult.NewData)
NSLog("Download From Remote Notification%#",userInfo)
}
2.Enable Remote notification
No user Interaction is needed in silent push notification
Here is good article which explains step by step guide
http://www.g8production.com/post/72656082173/ios7-multitasking-silent-notifications

Related

Is a iOS silent notification received when the app is killed

when sending a background push with "content-available": "1", to an app that is killed by the user, the application is not launched into the background mode and the application:didReceiveRemoteNotification:fetchCompletionHandler: is not called as the Apple doc say:
Use this method to process incoming remote notifications for your app. [...]In addition, if you enabled the remote notifications background mode, the system launches your app (or wakes it from the suspended state) and puts it in the background state when a remote notification arrives.
However, the system does not automatically launch your app if the user has force-quit it.
My question is: Is there is any way to access this silent push payload the next time the user starts the application?
I tried using the launchOptions of the didFinishLaunchingWithOptions method but they do not contain the push payload.
NSDictionary *userInfo = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];
My use case is that I rely only on the push channel to receive data to the app but the app cannot pull them.
Short answer is: no, you cannot.
You also won't be able to use VoIP pushes, the only option would be to use regular pushes with a push notification service extension. Share a keychain between your app and this extension, save the push payload in the keychain when receiving a notification and retrieve it with your app when it enters foreground.
Downside is you will need to present a visual notification to the user, but it can be silent, and you can choose to present whatever text you want (the best option will depend on what your app does and what's the purpose of this notification).
You may use a VoIP Push message, see here:
Voice Over IP (VoIP) Best Practices
There are many advantages to using PushKit to receive VoIP pushes:
[...]
Your app is automatically relaunched if it’s not running when a VoIP push is received.
[...]
Be aware, that your app must have background mode with VoIP capability enabled, which may be an issue for app store approval if misused.
Looking at the documentation, it seems like you should implement this method:
optional func application(_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable : Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void)
Within that method, write your code to store the payload (userInfo). Maybe store it in the userDefaults temporarily. Then when the application launches, check to see if the payload is available.

APNS: Receive silent Remote Notification if app was force quit

I am looking desperately for a way to receive silent remote notifications when the user has force quit his app.
I already experimented with this a while ago.
The only way to do that, was to remove the content-available flag. But then it wasn't a silent notification anymore. The main use case was to download additional content to the remote notification and only then schedule a local notification in turn.
As the new UNNotification Framework was introduced they also introduced the new Notification Service Extension which provides an elegant way to download content corresponding to a remote notification.
But there is still no way to do the same with silent notifications when the app is force closed. Or did I miss something ?
PS: Maybe it is a duplicate, but other threads do not respect the Notification Service Extension.
When app force closed. AppDelegate method:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
}
will not called. But if your json payload contain aps you will see instant message, after you swipe (or click on notification) method will be called.
You can look google and find table of difference silent and normal state and their work in other Application State
Finally I found the answer in localisation also discussed here:
Change language of alert in banner of Push Notification
I also use the new Notification Service Extension in combination to alter content before the notification is delivered.

iCloud & Core Data: Possible to get NSPersistentStoreDidImportUbiquitousContentChangesNotification while app is in background?

My app uses local notifications based on the timing of events logged with Core Data.
Any time there is a significant change in my Core Data store on the device, I call a function called updateLocalNotifications() that clears existing local notifications and sets up new ones based on the updated data in Core Data.
My NSPersistentStoreCoordinator for Core Data is set up with NSPersistentStoreUbiquitousContentNameKey, so it syncs across devices automatically using iCloud.
Ideally, if the user is running my app on two or more devices, I'd like to be able to run updateLocalNotifications() on all devices whenever the Core Data on iCloud changes.
I have this simple code in AppDelegate to listen for and respond to changes to data on iCloud:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// update local notifications whenever new iCloud data is received
notificationCenter.addObserver(self, selector: #selector(updateLocalNotifications), name: NSPersistentStoreDidImportUbiquitousContentChangesNotification, object: nil)
...
return true
}
If the app is open and in the foreground on both devices and I log an event on one device, I get the NSPersistentStoreDidImportUbiquitousContentChangesNotification on the other device within about 20 seconds.
The problem is I don't ever seem to get NSPersistentStoreDidImportUbiquitousContentChangesNotification when the app is running in the background on the second device. I've done lots of digging, but can't seem to find whether the iCloud sync is actually supposed to be happening in the background, or will only ever happen when my app is in the foreground. I'm still testing this to see if it's just a longer update interval when the app is in the background.
Possible Solution #1 (doesn't seem feasible based on testing so far, but this is what I want to do)
At this point, I'm looking for a solution to get the second device to check iCloud for changes while it's in the background and so a NSPersistentStoreDidImportUbiquitousContentChangesNotification is triggered when there are changes and firing this notification, even if it's less frequently than when the app is in the foreground. There are definitely drawbacks for this approach, like it won't be called if the person manually quits the app after launching it.
Possible Solution #2 (seems possible but complicated)
Another possible solution I'm considering would be to set up a server and use silent push notifications with content-available. That way, when someone logs an event on one device I would ping the server and ask it to send a content-available push to the user's other devices, and I could call updateLocalNotifications() when responding to that push notification. This has a few drawbacks. One is that the content-available push would not work if the app has not been launched after the device is booted or has been manually quit (similar to Solution #1). A second is that it involves a lot more overhead of setting up a server and pinging a server every time the events on a device change, even though that info is already being sent to a server via iCloud.
I've found a few other similar questions (like this one: How can I act on Core Data iCloud sync notification when the app is in the background?), but they don't put forward any possible solutions, so I thought it was worth posting my situation and possible solutions in case there are other people trying to work through a similar problem.
I would prefer a UX design solution for this problem.
It is questionable that the user wants to have your reminders pop up on all her devices. You should provide a setting where the user can switch them off, or rather, on. Make it clear to the user that the reminders will be device specific and that they will only be updated when the app is active, but based on the input from other devices.
For most users this will be expected and acceptable behavior.

Scheduling a second notification if first is ignored in swift (or completing any action if notification is ignored)

So I have an app currently on the app store that schedules 10 notifications in advance assuming you miss one you will still get a second chance or ten. Now before you think I will be bothering the person, the notification is very important to the functionality of the app and really is the main purpose. The app was built for iOS 7 so at that time there was no "handleActionWithIdentifier" which can, from my understanding, complete actions for the app even if it is closed depending on the users response to the notification. This update was very helpful for the app as it eliminates part of my problem of having to open the app to respond to the notification (the notifications ask the user a question and depending on the answer, completes something).
The problem that remains is detecting if the notification was missed, how would I make another notification appear, for example the next day, if the notification is dismissed or ignored. I have searched this on google and stack overflow and from my understanding all previous questions have been asking how to detect if the notification was missed one the app is opened which I do not need.
At this point, I can properly run code if the user responds to the notification by pressing one of the options on the notification by this :
func application(application: UIApplication, handleActionWithIdentifier identifier: String?, forLocalNotification notification: UILocalNotification, withResponseInfo responseInfo: [NSObject : AnyObject], completionHandler: () -> Void) {
var userInfo = [NSObject: AnyObject]()
userInfo["text"] = responseInfo[UIUserNotificationActionResponseTypedTextKey]
NSNotificationCenter.defaultCenter().postNotificationName("text", object: nil, userInfo: userInfo)
print(userInfo)
completionHandler()
}
as of right now, I am just taking textfield input and printing it but I could launch a second notification if I wanted. Is there a method to detecting when a notification is missed and scheduling another notification?
There is always a chance that it is still not possible to do what I want and I would just schedule 10 notifications in advance which seems sloppy and does not let me make the response as iterative.
TLDR; how do I detect and run code if a local notification is missed WITHOUT opening the app
BTW: if you have answers, swift is the preferred language
You can use a mixture of Background Fetch and Some kind of timestamp test.
For instance:
When you schedule a notification you can keep some logic that would let you track if that notification was ignored or not. Maybe keep some data in NSUserDefaults holding which was the last Notification sent and when it should be launched by the O.S.
One way could be to check for that timestamp:
If you launch this test after the moment in which it was supposed to launch (and maybe a bit late, just in case the user see it but is still not ready to answer) and you haven't still marked it as not ignored, then the user may have ignored or missed your notification.
This test should be able to be used in your AppDelegate.
Then, enable Background Fetch capability in Background Modes.
This will give some CPU time to your app (when iOS thinks is a good
time for that) and you can seize the opportunity ;-).
For being able to do that you will need to add proper function into your AppDelegate implementation:
func application(application: UIApplication, performFetchWithCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
// your code
}
In this function's body, run your "test for ignored notification" and schedule new notifications if needed.
Don't forget to call completionHandler as soon as you finish your test!

Execute code in background when push notification is received

I'm trying to find out what is actually possible on iOS when it comes to background tasks.
I have an app which is running in the background and tracking location changes on the device.
Now, is it possible to send a push notification to the device and have the device send the current location to a server without needing the user to open the app so it runs in the foreground?
I know this question is a bit old but I'm answering for those who, like me, arrived here long after the question was asked.
Now, is it possible to send a push notification to the device and have the device send the current location to a server without needing the user to open the app so it runs in the foreground?
Yes. You can now do that. I'm currently doing something pretty similar in my app. There are some other SO questions that now correctly state this. This is one
Basically, you have to enabled Background Execution for Remote Notifications. You can do this in XCode by going to your app's target. Open the Capabilities tab enabling the Background Modes feature and checking the Remote Notifications item in the checklist. (I'm assuming you already have enabled the Push Notifications feature).
With this the code you use to handle notifications in foreground will also serve you in background as
the application:didReceiveRemoteNotification:fetchCompletionHandler method will be called while your app is in background.
Here's a sample code in Swift 3.0:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
// Print full message.
print(userInfo)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
// Print full message.
print(userInfo)
completionHandler(UIBackgroundFetchResult.newData)
}
You may wanna check out this SO question (and accepted answer) about how to handle network request in background. Background request not execute Alamofire Swift
Check out the docs about Background Execution. Particularly the section about Push Notifications
Unfortunately I don't think so. When your app is in a suspended (freezed) state, push notifications are managed by SO, users need to reopen the app. They other way around is to create local notification for significant changes, when the notif arrives your app has a minimum amount of time, it will be not enough to post data, but you can study something. I will suggest you to read this question it talks about bluetooth and geolocation link
It's impossible. This OS has one principle —— user should know what you(your app) have done. When your app is suspended,your push message will be received by the notification center.The only way let your app know this thing happened is to launch your app through the notification center.so.....

Resources