I have a local notification which fire every minutes. I have done that part. But my problem is I want to count the notification and (count=15) then it's stop it. I can do that part in application running state. How can I achieve in background mode?
And also I want to track how many notification are fire? Is it possible in background mode.
//below is my notification delegate method
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
if (notification) {
// notification code goes here
}
}
Any demo code then appreciate. Thanks in advance.
You cannot really do that. Only way is to setup 15 notification in a row and keep your own list with dates. iOS is not giving you access to notification list or anything. What's more they don't have to be fired if user blocked them.
So I would advice to make own list with events + dates and manage them independently from notifications - especially when you have some important logic to be run based on that you cannot use notifications for that.
save your counter in the user defaults in didReceiveLocalNotification:
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
int counter = [[userDefaults valueForKey:#"notiCounter"] intValue];
counter =+ 1;
if (counter == 15) {
} else {
[userDefaults setValue:[NSString stringWithFormat:#"%i",counter] forKey:#"notiCounter"];
[userDefaults synchronize];
}
of course you have to initialize the counter and store in didFinishLaunchingWithOptions.
Related
I have been working with local notifications. But the problem is the application icon badge number is not incrementing with local notifcations fired. I tried .applicationIconBadgeNumber+1;
But it's not giving any effect. The application icon badge number is always 1.
enter code here
- (IBAction)save:(id)sender
{
eventitem=textfield.text;
NSDate *newdate=self.datepick.date;
UIApplication *app=[UIApplication sharedApplication];
notifyalarm=[[UILocalNotification alloc]init];
if (notifyalarm)
{
notifyalarm.fireDate=newdate;
notifyalarm.timeZone=[NSTimeZone defaultTimeZone];
notifyalarm.alertBody=eventitem;
notifyalarm.applicationIconBadgeNumber=[UIApplication sharedApplication] .applicationIconBadgeNumber+1;
[app scheduleLocalNotification:notifyalarm];
}
}
UPDATE
After seeing your code I would suggest to use following before setting badge value
NSUserDefaults* userDefs = [NSUserDefaults standardUserDefaults];
//old val
NSInteger iconBadge = [userDefs integerForKey:#"myBadgeVal"];
//updatge val
iconBadge++;
//store
[userDefs setInteger:iconBadge forKey:#"myBadgeVal"];
[userDefs synchronize];
//set as icon badge
notifyalarm.applicationIconBadgeNumber=iconBadge;
However I'm not sure when 'save' method is called. Make sure this method is called as many times as you expect.
You have to handle locally this number, as [UIApplication sharedApplication] .applicationIconBadgeNumber will always be 0(as you do not update this value anywhere). You could use NSUserDefaults if you wish. Also please provide some code so we can be more helpful.
If your first Settled LocalNotification will fire first then you can use following way to set BadgeCount.
notifyalarm.applicationIconBadgeNumber = ([[[UIApplication sharedApplication] scheduledLocalNotifications] count] + 1);
My App receives APNS Push Notifications, and when a user receive more than one NSNotification, he should be able to open the app in a specific view according the NSNotification tapped.
So in the method
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:
(void (^)(UIBackgroundFetchResult))completionHandler
I added this code to save all the notifications
if (self.notifications == nil) {
self.notifications = [[NSMutableArray alloc] init];
}
[notifications addObject:userInfo];
And every time the app becomes active again it does this
- (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.
[notifications removeAllObjects];
application.applicationIconBadgeNumber = 0;
}
Before removing all the objects and setting the badge to zero, I would like to handle which NSNotification made my app open from the background. And once I have which push NSNotification it was, I would like to pass all the data to a specific view.
Based on your comment about UILocalNotification usage
UILocalNotification has a userInfo property. When you create your local notification from the push notification, set the appropriate information into this property and then when the app delegate receives application:didReceiveLocalNotification: you can use that into to update your UI.
If you not use new iOS7 background fetch notifications.
In - (void)applicationDidBecomeActive:(UIApplication *)application before removing all object from notification array, check for notification
NSDictionary * myNotification = [notifications lastObject];
if (myNotification)
{
// is last notification
}
Is will work because app receive only notification that user tap on it
Send with your push notification, data, and use it when your app receives it.
In this example, i'm using the image file and alert, and sending it to all the views that are registered for this Notification.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
//Posting the notificaiton to the use, if its valid:
NSDictionary *returnDic = [userInfo objectForKey:#"aps"];
if (![returnDic objectForKey:#"alert"]) {
return;
}
NSString *alert = [NSString stringWithFormat:#"%#",[returnDic objectForKey:#"alert"]];
if (![returnDic objectForKey:#"MagnetID"]) {
return;
}
NSString *magnetImage = [returnDic objectForKey:#"MagnetImage"];
NSDictionary *dictionaryToSend = [NSDictionary dictionaryWithObjectsAndKeys:magnetImage,MAGNET_IMAGE,alert,MAGNET_ERROR_MESSEGE, nil];
//Posting to the rest of the views, the messege:
[[NSNotificationCenter defaultCenter] postNotificationName:USER_MESSEGE_RECEAVED object:nil userInfo:dictionaryToSend];
NSLog(#"Notifications - userInfo=%#",userInfo);
}
What you may do, is save the data that you need, by UserDefults or whatever you prefer, and at the "applicationDidBecomeActive" method, use that data to show the right view.
Hope this helps
According to the Apple Docs, in order to find out if a user tapped on your push notification you are supposed to check the applicationState in application:didReceiveRemoteNotification:
If the value is UIApplicationStateInactive, the user tapped the action button; if the value is UIApplicationStateActive, the application was frontmost when it received the notification.
I have found that this is not always true. For example:
Double-tap the home button to reveal the system tray and enter "fast app switching mode", your application slides up to reveal other running applications and your app is put into the inactive state (even though it's still mostyle visible). If you receive a push notification in this mode your app delegate will still receive the application:didReceiveRemoteNotification: and at this point your applicationState is UIApplicationStateActive. According to the docs you should treat it like the user tapped the alert... but in this case they didn't. Not only that, the user didn't even see the push notification (possibly because the top of your application is cut off in this mode).
Does anyone know of a way to detect being in 'fast app switching mode' or handle the notification correctly?
I was able to fix it myself with some nifty checks...
Essentially the key to this whole thing is
-(void)applicationDidEnterBackground:(UIApplication *)application;
This method isn't called when you enter fast app switching (or control center) so you need to setup a check based on it.
#property BOOL isInBackground;
#property (nonatomic, retain) NSMutableArray *queuedNotifications;
And when you receive a notification...
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
UIApplicationState appState = application.applicationState;
// Check if we're in this special state. If so, queue the message up
if (appState == UIApplicationStateInactive && !self.isInBackground) {
// This is a special case in which we're in fast app switching or control center
if (!self.queuedNotifications) {
self.queuedNotifications = [NSMutableArray array];
}
// Queue this to show when we come back
[self.queuedNotifications addObject:userInfo];
}
}
And then when we come back...
- (void)applicationDidBecomeActive:(UIApplication *)application {
application.applicationIconBadgeNumber = 0;
if (!self.isInBackground) {
// Show your notifications here
// Then make sure to reset your array of queued notifications
self.queuedNotifications = [NSMutableArray array];
}
}
One more thing you may want to do is check for this special case of going to fast app switching and the user going somewhere else. I do this just before setting the isInBackground BOOL. I choose to send them as local notifications
-(void)applicationDidEnterBackground:(UIApplication *)application {
for (NSDictionary *eachNotification in self.queuedNotifications) {
UILocalNotification *notification = [self convertUserInfoToLocalNotification:eachNotification];
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
}
self.queuedNotifications = [NSMutableArray array];
self.isInBackground = YES;
}
So, here is my life story that I can't seem to figure out what's wrong!!!
I have an app that's already in the store and it has a weird issue which it gives out mixed results.
I have two switches in my main view both controls local notification with repeat intervals.
now I've set up the switches right and ready to go. (I guess).
However, when repeat intervals are scheduled they have to be cancelled again when the user decided not to receive notifications. So, I had my switches coded like that:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
BOOL switchOn = [userDefaults boolForKey:#"switchO"];
if (switchOn) {
[self Firstnotif];
[self Secondnotif];
[self Thirdnotif];
[self Lastnotif];
}
else { [[UIApplication sharedApplication] cancelAllLocalNotifications]; }
BOOL switchOn2 = [userDefaults boolForKey:#"switchO2"];
if (switchOn2) {
[self Firstnotif];
}
else { [[UIApplication sharedApplication] cancelAllLocalNotifications]; }
}
notice I have used the method Firstnotif twice in both switches.
My issues are:
I used to have only one switch and when they turn the first switch on to receive these four notification, doesn't work with all of the users. so I tell them to switch it off, press home button, open app again switch it on and home button again. It works!!!! why?
Now, since I've added another switch new mixed results are appearing.
the second switch is to only fire first notification with it's repeat interval. Some say it works, some say not. others say when I turn the other one it does and does not. What are they facing here??
My questions,
Am I canceling the repeat intervals in the right way?
What could be wrong with my app? and I'll provide you with more codes if needed.
I appreciate your inputs as I've spent weeks on these issues with no luck.
I solved it!
I replaced the cancellation request under applicationDidBecomeActive method and removed my else
guess what? It worked!!! :)
I need to run specific code if a local notification was fired while the application was in the background and has now entered the foreground. One way to do this is to get the badge count, is there a better way?
Check out the docs at http://developer.apple.com/library/mac/#documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/IPhoneOSClientImp/IPhoneOSClientImp.html
Your App Delegate can detect notifications when the app is in the background
- (void)application:(UIApplication *)app didReceiveLocalNotification:(UILocalNotification *)notif {
NSString *itemName = [notif.userInfo objectForKey:ToDoItemKey]
[viewController displayItem:itemName]; // custom method
application.applicationIconBadgeNumber = notification.applicationIconBadgeNumber-1;
}