I have a Local Notification which fire every minute. Its fire date & other data are taking into the local database. I am used the notification delegate method for notification which gives me notification Active & Background mode.
When Notification fire then update sqlite database every notification (every minute). when notification fire it’s update sqlite database In Application Active State. That’s state working done.
my code like
-(void)application:(UIApplication *)application
didReceiveLocalNotification:(UILocalNotification *)notification {
// I recieved a notification
if (notification) {
[Update DataBase Method];
}
}
But my problem is when Application goes Background Mode then Database not Update only Notification Received.
How can I update my database its goes in Background mode (or any state) at every notification fire?
Here is the apple site that explain the task in background/suspend mode..
(Recommended) Register for any notifications that report system changes your app needs. When an app is suspended, the system queues key notifications and delivers them when the app resumes execution. Apps should use these notifications to make a smooth transition back to execution. For more information, see “Processing Queued Notifications at Wakeup Time.”
So if app is queuing the notification than you can access this notification data when your app opens next time.
So what you should have to do is that ..
When your app start check that if there is any notification.
If there is than do the database operation according to the data of the notification
Do the Database update task from applicationDidBecomeActive method. applicationDidBecomeActive method will called whenever your app become active.
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// Restart any tasks that were paused (or not yet started) while the application was inactive.
//If the application was previously in the background, optionally refresh the user interface.
NSLog(#"Dilip applicationDidBecomeActive");
}
I think this will do the work...
Related
In my app I am using a daily silent push to trigger some calculations inside my app and based on the calculation result I am triggering a local notification.
Say for example: A daily goal.
Once the silent notification reaches my app, I trigger a background method to calculate the user data and compare whether his/ her data achieved a goal and if yes I trigger a local notification so that user can open the app and check.
It is not working consistently, sometimes I get it and sometimes don't. When I debugged, what I saw was that the execution get paused in between and execution gets resumed only if the user opens the app again or I trigger a silent push again. Not sure why the background execution (the calculation) gets paused, and if I trigger a push or if i manually try to open the app, I can see the breakpoint appearing back and it continues from the place it was paused.
I am wondering whether it is because of some time limit??
UPDATE:
I am using UrbanAirshipSDK and they have some handlers overridden and I am using the below method to handle the notification. This is written in the appdelegate and gets called when I get a notification when app is in background.
/**
* Called when a push notification is received while the app is running in the background
* for applications with the "remote-notification" background mode.
* Overridden by receivedBackgroundNotification:fetchCompletionHandler.
*
* #param notification The notification dictionary.
*/
- (void)receivedBackgroundNotification:(NSDictionary *)notification;
I first check for content-available in the payload and treat as silent and do the calculations. This works fine intermittently but not consistently. I am closing towards release dates and I really worried.
I assume that you use:
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler
In this case you should not forget to call completion handler and according to Apple docs you have only 30 seconds to do so:
As soon as you finish processing the notification, you must call the
block in the handler parameter or your app will be terminated. Your
app has up to 30 seconds of wall-clock time to process the
notification and call the specified completion handler block. In
practice, you should call the handler block as soon as you are done
processing the notification. The system tracks the elapsed time, power
usage, and data costs for your app’s background downloads. Apps that
use significant amounts of power when processing remote notifications
may not always be woken up early to process future notifications.
Four questions about Push Notifications.
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
UIApplicationState state = [application applicationState];
if (state == UIApplicationStateActive) {
//app is in foreground I can fetch
} else {
//App is in background, can I still fetch the server? Is there a time limit?
}
}
Using the code above, when the app is in background, can I still fetch the server? Is there a time limit? If the answer is: No, I cannot fetch the server in the background, are there alternatives?
Is there any other benefit of using silent notification besides triggering some method to run within 30 seconds when the app is in the background?
If using silent notification and the app is in the foreground, is the following method still called?
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
completionHandler(UIBackgroundFetchResultNewData);
}
In the payload does "content-available" : 1 calls the method in Q3 (above)? or is there anything else that can trigger the method in Q3?
Yes you can still fetch the server when the app is in background. For many apps, the background state is just a brief stop on the way to the app being suspended.
No this is the main benefit of using silent notification see this link.
Yes application:didReceiveRemoteNotification:fetchCompletionHandler: is called regardless of app state.If app is suspended or not running, then the system wakes up or launches your app and puts it into the background running state before calling the method.
This method is intended for showing the updated content to the user.When this method is called, your app has up to 30 seconds of wall-clock time to perform the download operation and call the specified completion handler block. If the handler is not called in time, your app will be suspended.
Yes it calls application:didReceiveRemoteNotification:fetchCompletionHandler:, If you want a push notification to wake your app up in the background you need to enable the Remote Notifications capability and then implement the code to handle that remote notification (either by detecting it in the application:didFinishLaunchingWithOptions: if your app is not already running, or by implementing application:didReceiveRemoteNotification:fetchCompletionHandler: in the case your app is already running). In response to the remote notificaiton you would internally trigger your fetching code. Of course you also need to be doing registering for the remote notifications and sending the token to your server. please see this discussion
When receive a push notification and my application is totally closed, how can handle this info?
Only can get data from NSDictionary on this method didFinishLaunchingWithOptions: or
didReceiveRemoteNotification:
for example: when the user open the application how get data from the push notification?, and not when the user open the push notification directly.
Is there a method that responds and detect if a notification has not been read?
You'll want to implement
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler
This will launch your app if needed, then you'll want to save the data somewhere so when the user next's starts the app you grab the data and do something with it.
From Apples Doc's:
Discussion
Use this method to process incoming remote notifications for your app.
Unlike the application:didReceiveRemoteNotification: method, which is
called only when your app is running in the foreground, the system
calls this method when your app is running in the foreground or
background. 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 push
notification arrives. However, the system does not automatically
launch your app if the user has force-quit it. In that situation, the
user must relaunch your app or restart the device before the system
attempts to launch your app automatically again.
Just look into the method and I'm certain you'll figure it out :)
I did a quick google, these look like they will help:
SO example: didReceiveRemoteNotification: fetchCompletionHandler: open from icon vs push notification
The first tutorial i saw on it: http://hayageek.com/ios-background-fetch/
I am working on developing an Enterprise application where maintaining users session synced with device session is a key and required feature.
The basic requirement was to end user session from server as soon as user kills the app, but as there is know way we can get app termination event in code (except starting a background task which can run maximum for 10 mins), server remains unaware about app kill.
I made some workaround to solve this problem.
First, I Used background modes -
a) App downloads content from the network.
b) App downloads content in response to push notifications.
The idea is when user send app in background by switching to another app or by home button or locks device, app is sending a request to the server that app is going in background, and server get to know that app went in background.
-(void)applicationWillResignActive:(UIApplication *)application
{
// notify server that app is in background
}
As soon as server receives the request, it starts the timer for this specific device, which keep on counting apps time spent in background. For every five minutes server sends a request to the device which is in background to get its STATUS.
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary*)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{
NSDictionary *aps = [userInfo objectForKey:#"aps"];
NSLog(#"NOTIFICATION IN BG %#",[aps objectForKey:#"message"]);
NSString *message = [aps objectForKey:#"message"];
if([message isEqualToString:#"Please update your status"]){
// NOTIFY SERVER THAT APP IS IN BACKGROUND
}
if(application.applicationState != UIApplicationStateBackground){
[self application:application didReceiveRemoteNotification:userInfo];
}
completionHandler(UIBackgroundFetchResultNewData);
}
As soon as app again comes in foreground or become active app notifies server that it has become active.
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// notify server that app is in Foreground // server resets the background timer to 0 for corresponding device
}
This approach helps in tracking if app is terminated or not, if server does not get any response from the notification that it sent, it clears the user session from server.
NOW, There are two scenarios in 1st one it works perfectly as expected and in second it doesent.
CASE 1 : App in BackGround but DEVICE NOT LOCKED
App Launched
User logged in
App went in BG
Server has been notified that app is in BG.
Server starts timer.
Elapsed time exceeds 5 mins on server for this device (As app still in BG) .
Server sends notification.
App receives remote push notification in BG.
App notifies its status to server that is in BG (Hence server came to know that it is not terminated and user session should not be cleared off)
This cycle of remote notification and reply to server from device from BackGround goes on till the time either app becomes active again or it is terminated.
Works perfectly fine as expected.
CASE 2 : App in BackGround and DEVICE LOCKED
App Launched
User logged in
App went in BG
Server has been notified that app is in BG.
Server starts timer.
Device is lOCKED
Elapsed time exceeds 5 mins on server for this device (As app still in BG) .
Server sends notification.
Device receives Notification, Device displays banner for notification.
BUT App which is inactive mode does not receives remote push notification in BG.
As a Result App is not able to reply to the server
And whole cycle goes for a toss.
THE ULTIMATE QUESTION IS HOW TO MAKE IT WORK WHEN DEVICE IS LOCKED.
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
NSLog(#"user info %#",userInfo );
}
by this delegate method you can receive dictionary from server.And can do your work accordingly.This method will call in your app after click on notification in notification tray.
I have an app that has different downloaded content each day, but I want to automatically update this content each time its available and send a notification to the user when the app has already downloaded the content locally (running in background). Should I use the applicationDidEnterBackground?
- (void)applicationDidEnterBackground:(UIApplication *)application{}
but I was reading this background state may only last minutes and is must likely to enter background after the user changed to another app or clicked home, so how can I trigger this background state (when inactive) at 1:00 am for example? ... Another alternative could be just sending a notification to the user when new content is available and download it as soon as the user opens the app (but this is certainly plan B).
I'm open to suggestions
You can send a silent push notification. This works the same was as a normal push notification only that it doesn't make a sound or alert the user to the fact that they have received it. Your app will then be opened in the background by iOS and will run your code.
The push will then trigger this del method:
- (void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
You can then execute your code in the completion handler. There is a time limit and the silent push notifications are throttled by APNS automatically to prevent constant spamming.
The next time the user opens your app the new content will be preloaded and waiting for them. This seems to be what you are after ... ?
See: https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html#//apple_ref/doc/uid/TP40007072-CH4
Near the bottom there are two parts:
"Fetching Small Amounts of Content Regularly"
and
"Using Push Notifications to Initiate a Download"