Update badge icon when app is in background/suspended mode - ios

I want to update application badge icon when a notification is received. It works fine when app is running (active mode),but having trouble when trying to set it when app is in suspended/background mode. Want to achieve the same without using the 'badge' field in apns dictionary.
Here is what i am doing,
-(void) incrementOneBadge{
NSInteger numberOfBadges = [UIApplication sharedApplication].applicationIconBadgeNumber;
numberOfBadges +=1;
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:numberOfBadges];
}
-(void) decrementOneBadge{ NSInteger numberOfBadges = [UIApplication sharedApplication].applicationIconBadgeNumber;
numberOfBadges -=1;
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:numberOfBadges];
}
-(void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
UIApplicationState state = [application applicationState];
if (state == UIApplicationStateActive) {
}
else {
// Push Notification received in the background
[self incrementOneBadge];
}
[self handlePushNotificationsForState:application withDictionary:userInfo];
}

Related

how to handle Notification when app State is UIApplicationStateInactive

I am using following code to handle push notification.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
if(application.applicationState == UIApplicationStateInactive)
{
//************************************************************
// I only want this called when user click on notification.
//************************************************************
NSLog(#"Inactive");
if ([[userInfo valueForKey:#"noty_type"] isEqualToString:#"web"])
{
if([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:[userInfo valueForKey:#"url"]]])
{
dispatch_async(dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:[userInfo valueForKey:#"url"]]];
});
}
}
}
if((application.applicationState == UIApplicationStateActive)
{
// I am useing local notification when app in Forground
UILocalNotification* localNotification = [[UILocalNotification alloc] init];
localNotification.soundName = #"Default";
localNotification.alertBody = [userInfo valueForKey:#"msg"];
localNotification.userInfo = userInfo;
[[UIApplication sharedApplication] scheduleLocalNotification: localNotification];
}
}
This code open the url in safari browser. this code work fine When my app in background and notification come and I click on notification check the applicationState and open the url with [[UIApplication sharedApplication] openURL.
now the scenario that generate the problem.
I open my app .
and Down the notification UI
now Send the notification from server
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler method get called.
Now I get the ApplicationState == UIApplicationStateInactive .
"It open into the safari browser without any user interaction".
I only want this called when user click on notification.
So, How can I handle this condition ?
Try this.
if (application.applicationState == UIApplicationStateInactive || application.applicationState == UIApplicationStateBackground)
{
// do something when app open with notification
}
You have to know why the app is inactive. The two possibilities are that the app was in the background and the user is bringing it to the foreground (by tapping on the notification banner), or something like the notification center was pulled down or the user got a system alert.
To tell the difference, keep track of when the user enters the background. Just set a boolean in the applicationDidEnterBackground: delegate method, and clear it when the app is resigning active.
static BOOL didEnterBackground;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Launching the app is kind of like coming from background.
didEnterEnterBackground = YES;
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
didEnterBackground = NO;
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
didEnterBackground = YES;
}
Now you can check the variable didEnterBackground to determine how the app got to the inactive state when you're handling a notification.
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
if (application.applicationState == UIApplicationStateInactive) {
if (didEnterBackground) {
// The user tapped the notification
}
else {
// The app was inactive, but not in the background.
// Ignore notification, or do whatever the app does
// when receiving a notification while active.
}
}
}
Hope this help you
-(void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
}//iOS below 9
- (void)application:(UIApplication *)application
handleActionWithIdentifier:(nullable NSString *)identifier
forLocalNotification:(nonnull UILocalNotification *)notification
completionHandler:(nonnull void (^)())completionHandler {
// handling local and interactive notifcation
} // iOS 9 and above
Which is used to trigger the notification in background state.

how to handle NSLocal Notification in background?

For multiple Alarm Notification Alert?
If Application is Running in Background.
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notif{
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
if (application.applicationState == UIApplicationStateInactive )
{
NSLog(#"app not running");
}
else if(application.applicationState == UIApplicationStateActive )
{
NSLog(#"App is running");
}else if(application.applicationState == UIApplicationStateBackground){
NSLog(#"App is running in background");
}
}
In Addition to JAGAT's answer for iOS 8+ you need to ask for permission to register for listening to local notifications. And you can user this:
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification completionHandler:(void(^)())completionHandler{
}
And for permisson do this:
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
{
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings
settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge)
categories:nil]];
}
Use the following method in AppDelegate.m class.
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notif{
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
if (application.applicationState == UIApplicationStateInactive )
{
NSLog(#"app not running");
}
else if(application.applicationState == UIApplicationStateActive )
{
NSLog(#"App is running");
}else if(application.applicationState == UIApplicationStateBackground){
NSLog(#"App is running in background");
}
}
May be this is helpful for you to handle local notification in background.

Issue with implementing badges in ios

I am working in ios app in phonegap with pushnotification.i have added the below code in Appdelegate+notification.m
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
PushPlugin *pushHandler = [self getCommandInstance:#"PushPlugin"];
[pushHandler didFailToRegisterForRemoteNotificationsWithError:error];
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
NSLog(#"didReceiveNotification");
// Get application state for iOS4.x+ devices, otherwise assume active
UIApplicationState appState = UIApplicationStateActive;
if ([application respondsToSelector:#selector(applicationState)]) {
appState = application.applicationState;
}
if (appState == UIApplicationStateActive) {
PushPlugin *pushHandler = [self getCommandInstance:#"PushPlugin"];
pushHandler.notificationMessage = userInfo;
pushHandler.isInline = YES;
[pushHandler notificationReceived];
} else {
//save it for later
self.launchNotification = userInfo;
}
[UIApplication sharedApplication].applicationIconBadgeNumber = [UIApplication sharedApplication].applicationIconBadgeNumber + [[[userInfo objectForKey:#"aps"] objectForKey: #"badge"] intValue];
}
I am using pushNotification.java file for sending push message to our application in that i have mentioned payload.addBadge(1);
So in my app badge gets update onclick of notification Please suggest me how to do it while receiving notification

Local Notifications not working When enter applicationDidBecomeActive

I am using Repeat Local notofications to display alerts to the user. For this i used below code
UILocalNotification* localNotification = [[UILocalNotification alloc] init];
localNotification.fireDate = [[NSDate date] dateByAddingTimeInterval:60];
localNotification.alertBody = #"sss";
localNotification.alertAction = #"Show me the item";
localNotification.timeZone = [NSTimeZone defaultTimeZone];
localNotification.applicationIconBadgeNumber = [[UIApplication sharedApplication] applicationIconBadgeNumber] + 1;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
Using NSNotification Centre i will call the local notification every 60 seconds. It is working fine.
Also in Appdelegate i use the following code:-
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
NSLog(#"Received");
UIApplicationState state = [application applicationState];
if (state == UIApplicationStateActive) {
[[NSNotificationCenter defaultCenter] postNotificationName:#"RestartProcess" object:self];
}
application.applicationIconBadgeNumber = 0;
}
Also
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UILocalNotification *locationNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (locationNotification) {
// Set icon badge number to zero
NSLog(#"Yes Notid=fications is predsent");
application.applicationIconBadgeNumber = 0;
}
return YES;
}
My problem is when local notification starts, i pressed on home button then waited to display. After the time period display a notification message.
When i clicked on app icon the process is stopped.After that Local notifications not working.But when i was clicked on Notification Message it will works right.How i can fix the problem.Can any one help me to do this. Thanks in advance..
didReceiveLocalNotification is only called when you hit on notification messaage. If you want to do it in applicationDidBecomeActive you have to do it manually.
You can check badge number count(if notification consists badge) like :
-(void) applicationDidBecomeActive:(UIApplication *)application
{
if(application.applicationIconBadgeNumber >= 1)
{
//Do you stuff here
application.applicationIconBadgeNumber = 0;
}
}
When you press home button:
UIApplicationState state = [application applicationState];
// at this time, state == UIApplicationStateInactive
When you click your application, i think you should implement in this method:
- (void)applicationDidBecomeActive:(UIApplication *)application- (void)applicationWillEnterForeground:(UIApplication *)application
{
UIApplicationState state = [application applicationState];
application.applicationIconBadgeNumber = 0;
//state at this time is UIApplicationStateInactive
if (state == UIApplicationStateInactive) {
[[NSNotificationCenter defaultCenter] postNotificationName:#"RestartProcess" object:self];
}
}
Hope this helps you

How to clear just the notification in iOS

If the user has alert style set to Banners. They can receive more than 1 notification without them being prompted to clear it. They then go to use their phone, and they have say 3 stored. If the click on the latest one & it opens the App, I want to only clear just this one notification, I also need to go badgeCount--;
How can I achieve it with the code below? (At the moment it's set to clearing all which I don't want...) I've also noticed that sometimes it DOES update the badge number. But if I toggle back to the iOS Home screen, and pull down the notifications menu, it's still there!
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
if([[userInfo valueForKey:#"aps"] valueForKey:#"alert"] != nil) {
NSString *message = [[userInfo valueForKey:#"aps"] valueForKey:#"alert"];
if(message != nil) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Usage Alert"
message:message delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Ok", nil];
[alertView show];
[[UIApplication sharedApplication] setApplicationIconBadgeNumber: 0];
[[UIApplication sharedApplication] cancelAllLocalNotifications];
}
}
}
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
UIApplication *app = [UIApplication sharedApplication];
NSInteger badgeNumber = [app applicationIconBadgeNumber];// Take the current badge number
badgeNumber--; // decrement by one
[app setApplicationIconBadgeNumber:badgeNumber]; // set ne badge number
[app cancelLocalNotification:notification]; // cancel the received notification. It will clear the notification from banner alos
}
You can add
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
to your app delegate. This will be called and there you can use
[[UIApplication sharedApplication] cancelLocalNotification:notification];
to remove the specific notification and decrement the badge count.
I want to warn against calling
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:bg_NUM]
from
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
method!
If your scheduled local notification with some badge number, then badge will be set asynchronously some milliseconds after enter to -didReceiveLocalNotification
for sample:
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
// ^^^ maybe not reset badge to 0!! ^^^
}
another code:
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
sleep(1); //waiting for system is set our scheduled badge
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
// ^^^ most chances for reset badge to 0 ^^^
}
Testing code, screen touches schedule local notifications
and calculate delay before system real set badge:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
UILocalNotification *localNotif = [[[UILocalNotification alloc] init] autorelease];
localNotif.applicationIconBadgeNumber = rand()%100+1;
localNotif.fireDate = [NSDate dateWithTimeIntervalSinceNow:1];
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
}
[...]
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();
while ([UIApplication sharedApplication].applicationIconBadgeNumber == 0) sleep(0);
NSLog(#"badge set: %d after %f sec.", [UIApplication sharedApplication].applicationIconBadgeNumber, CFAbsoluteTimeGetCurrent()-startTime);
}
output:
badge set: 41 after 0.000839 sec.
badge set: 9 after 0.000754 sec.
badge set: 56 after 0.076026 sec.
badge set: 17 after 0.069889 sec.
badge set: 8 after 0.056245 sec.
badge set: 71 after 0.120729 sec.
badge set: 28 after 0.122720 sec.
badge set: 17 after 0.000758 sec.
this testing in iOS 4.2/4.3/5.0/6.1 on different devices
Be careful when you reset badge number in -didReceiveLocalNotification message!
(this true only for LocalNotification /not remote push/ and only if application is active on
receive moment)

Resources