local notification "didReceiveLocalNotification" calls twice - iphone

I am handling local notifications using:
- (void)application:(UIApplication *)app didReceiveLocalNotification:(UILocalNotification *)notif
And to schedule a local notification:
- (void)scheduleNotificationWithInterval:(int)minutesBefore {
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
if (localNotif == nil)
return;
NSDate *fireDate = [NSDate date];
localNotif.fireDate = [fireDate dateByAddingTimeInterval:minutesBefore*60];
localNotif.timeZone = [NSTimeZone defaultTimeZone];
localNotif.repeatInterval = kCFCalendarUnitMinute;
localNotif.alertBody = [NSString stringWithFormat:NSLocalizedString(#"LocalEvent notification in %i minutes.", nil),minutesBefore];
localNotif.alertAction = NSLocalizedString(#"View Details", nil);
localNotif.applicationIconBadgeNumber = 1;
NSDictionary *infoDict = [NSDictionary dictionaryWithObjectsAndKeys:#"This is dict, you can pass info for your notification",#"info",nil];
localNotif.userInfo = infoDict;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
[localNotif release];
NSLog(#"Event scheduled");
}
When I receive a notification, didReceiveLocalNotification: is called twice.
Am I doing something wrong?
Please help.
Thanks.

I think there is a known bug in the simulator, that fires the delegate notification method twice. It should not happen on the device, tethered to XCode or not.

i was also facing the same problem and the solution which i find is that write this code in didReceiveLocalNotification
if (state == UIApplicationStateActive) {
NSLog(#"UIApplicationStateActive");
}
else if(state == UIApplicationStateInactive){
NSLog(#"UIApplicationStateInActive");
}
here in these condition i just write the code which i want my application to do on notification , in Active mode and in inactive mode

I suspect that the notification is being retriggered as long as its in the same second still. I fixed it by setting the fireDate to nil in the handler:
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:notification.alertAction message:notification.alertBody delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
notification.fireDate = nil;
}

I had the same issued. It was caused by calling 'registerUserNotificationSettings' twice in the AppDelegate's 'didFinishLaunchingWithOptions.' However, simply removing the duplicate call did not fix the problem yet. I had to delete the app and then rebuild. Only then did the double local notification issue get fixed.

Related

iOS Alarm Clock

I have created a simple alarm notification App through which I can get real time, set alarm on or off, and play a single tone audio. But I need to play a sound which should start with a class VOID.
Below is the code:
To get and start alarm notification:
- (void)viewDidLoad {
[super viewDidLoad];
dateTimerPicker.date = [NSDate date];
}
- (void)presentMessage:(NSString *)message {
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"Hello!"
message:message
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles: nil];
[alert show];
}
- (void)scheduleLocalNotificationWithDate:(NSDate *)fireDate {
UILocalNotification *notification = [[UILocalNotification alloc]init];
notification.fireDate = fireDate;
notification.alertBody = #"Time to wake up!!";
notification.soundName = #"PhoneOld.mp3";
[self playPause];
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
}
- (IBAction)alarmSetOn:(id)sender{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.timeZone = [NSTimeZone defaultTimeZone];
dateFormatter.timeStyle = NSDateFormatterShortStyle;
dateFormatter.dateStyle = NSDateFormatterShortStyle;
NSString *dateTimeString = [dateFormatter stringFromDate:dateTimerPicker.date];
NSLog(#"Alarm Set: %#", dateTimeString);
[self scheduleLocalNotificationWithDate:dateTimerPicker.date];
[self presentMessage:#"Alarm ON!"];
}
- (IBAction)alarmSetOff:(id)sender {
NSLog(#"Alarm Off");
[[UIApplication sharedApplication] cancelAllLocalNotifications];
[self presentMessage:#"Alarm OFF!"];
}
This is my VOID:
- (void)playPause {
RADAppDelegate *appDelegate = (RADAppDelegate *)[[UIApplication sharedApplication] delegate];
if (appDelegate.radiosound == 0){
[appDelegate.radiosound play];
} else {
[appDelegate.radiosound pause];
}
}
How can I set the alarm to start playing the radiosound if is rated 0, like a:
notification.soundName = [self playPause];
But I know this is a NSString.
You don't need to assign a sound name to scheduled notification, just invoke the playPause method and get the name of sound file from notification, as shown below and just assign it to NSString and set property to it in appDelegate and access it to play that file.
AppDelegate.h
#property (nonatomic,strong) NSString *nsStr_soundFile;
AppDelegate.m
#synthesize nsStr_soundFile;
- (void)application:(UIApplication *)application
didReceiveLocalNotification:(UILocalNotification *)notification {
//Give call to play sound method.
self.nsStr_soundFile=notification.soundName;
VOID *obj=[VOID alloc]init];
[obj playPause];
}
You can make a trick with opting out of iOS multitasking by setting in your app .plist file this key UIApplicationExitsOnSuspend to YES as written here
When an app opts out, it cycles between the not-running, inactive, and
active states and never enters the background or suspended states.
An app that runs in the pre-multitasking compatibility mode keeps
running when the user locks the device while the app is in the
foreground. All the app has to do is wait for the alarm time and
execute its custom code.

iOS: Local Notifications Don't Fire On Time

The issue is that my notifications aren't going through when they are set up to. I put a date picker in the nib and a button underneath it. The user is supposed to set the date in the picker, and clicking the button set up the notification to fire 60 hours before the date. So, it looks like I'm just having issues with getting the firedate to recognize the date in the date picker. Here is the code, it is in my view controller:
- (IBAction)scheduleNotifButton:(id)sender {
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
NSDate *selectedDate = [self.datePicker date];
localNotif.fireDate = [selectedDate dateByAddingTimeInterval:-60*60*60];
localNotif.timeZone = [NSTimeZone defaultTimeZone];
localNotif.alertBody = #"Event is in three days!";
localNotif.alertAction = nil;
localNotif.soundName = UILocalNotificationDefaultSoundName;
localNotif.applicationIconBadgeNumber = 0;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Event scheduled."
message:#"You will be notified three days before the event."
delegate:nil
cancelButtonTitle:#"Okay."
otherButtonTitles:nil];
[alert show];
}
And here is some additional code if that helps, this is more code from my view controller that deals with saving the date in the picker that the user entered:
- (IBAction)dateChanged:(id)sender
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDate *selectedDate = [self.datePicker date];
[defaults setObject:selectedDate forKey:#"ImportantDatesViewController.selectedDate"];
[defaults synchronize];
}
- (void)viewDidLoad {
NSDate *storedDate = [[NSUserDefaults standardUserDefaults]
objectForKey:#"ImportantDatesViewController.selectedDate"];
if (storedDate == nil) {
storedDate = [NSDate date];
}
[self.datePicker setDate:storedDate animated:NO];
}
I've been digging through this code for 3 days now and cannot figure out why my notifications aren't going through when they are supposed to. Any help is very much appreciated, thank you!
Do you understand that UILocalNotifications and remote notifications are different things?
In didRegisterForRemoteNotificationsWithDeviceToken you get the device token to be used for remote notifications. Remote notifications are sent from a server so you have to save that token on your server and then use your server to send any remote notifications.
Why don't you change this:
localNotif.fireDate = [eventDate dateByAddingTimeInterval:-630*60];
to this:
localNotif.fireDate = [[NSDate date] dateByAddingTimeInterval:60];
Then the local notification should go off in a minute. Maybe the problem is the date that you are setting.
How do you know your notifications aren't working?
Local and push notifications are different. If your app is currently active, a local notification won't actually show an alert message. It will just call a UIApplicationDelegateMethod
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification

Showing Local Notifications using Location Manager, While app is in the background

I am new to iPhone Programming .I have developed one application for checking user entered into a particular region.But i need to check in Background.In background i am checking but the problem is repeating the UILocalNotification alerts .
So how to prevent the repeated UILocalNotifications
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSLog(#"running in background ...");
[self checkRegionEntered];
CurrentlattitudeValue1 =newLocation.coordinate.latitude;
CurrentlongitudeValue1=newLocation.coordinate.longitude;
}
-(void)checkRegionEntered
{
if ([testRegion containsCoordinate:currentCoordinates])
{
[[UIApplication sharedApplication] cancelAllLocalNotifications];
Class cls = NSClassFromString(#"UILocalNotification");
if (cls != nil)
{
UILocalNotification *notif = [[cls alloc] init];
NSDate *now = [NSDate date];
[notif setFireDate:now];
if([Obj.NotesGeo length])
[notif setAlertBody:Obj.NotesGeo];
else
{
[notif setAlertBody:[NSString stringWithFormat:#", you have arrived at %#",Obj.NameGeo]];
}
[notif setAlertAction:#"Launch"];
notif.soundName=[NSString stringWithFormat:#"%#.wav",Obj.Ringtone1];//[NSString stringWithFormat:#"%g",Obj.LatitudeGeo]
NSDictionary *userDict = [NSDictionary dictionaryWithObject:[NSString stringWithFormat:#"%f",Obj.LatitudeGeo] forKey:kRemindMeNotificationDataKey];
notif.userInfo = userDict;
}
}
}
This may help. This logic is designed to ensure that your notification will only fire once, and that the same alert is displayed regardless of whether the app is in the foreground or background when it fires.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Add the view controller's view to the window and display.
[self.window addSubview:viewController.view];
[self.window makeKeyAndVisible];
//detect if app was launched by notification
UILocalNotification *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (notification)
{
//trigger our custom notification handler
[self handleLocalNotification:notification];
}
return YES;
}
- (void)handleLocalNotification:(UILocalNotification *)notification
{
//this is our custom method to handle the in-app notification behaviour
[[[[UIAlertView alloc] initWithTitle:#"You have a notification"
message:#"Yay!"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil] autorelease] show];
}
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
//this standard application delegate method is called under the following circumstances
//1. the app is running in the foreground when the notification fires
//2. the app was running in the background when the notification fired, and the user pressed the action button
//confusingly, if the app was not running when the notification fired, this method won't be called at startup
//automatically and you need to check for the notification key in the launch options instead
if ([UIApplication sharedApplication].applicationState != UIApplicationStateBackground)
{
//this code emulates the same behaviour as when a local notification is received
//when the app is not running (except for playing the sound)
//store notification temporarily
[lastNotification release];
lastNotification = [notification retain];
//get button labels
NSString *actionButton = nil;
NSString *cancelButton = #"Close";
if (notification.hasAction)
{
actionButton = (notification.alertAction)? notification.alertAction: #"View"; //defaults to "View" if nil
cancelButton = #"OK";
}
//show alert
[[[[UIAlertView alloc] initWithTitle:[[NSBundle mainBundle] objectForInfoDictionaryKey:#"CFBundleDisplayName"] //name of application
message:notification.alertBody
delegate:self
cancelButtonTitle:cancelButton
otherButtonTitles:actionButton, nil] autorelease] show];
}
else
{
//trigger our custom notification handler
[self handleLocalNotification:notification];
}
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex != alertView.cancelButtonIndex)
{
//trigger our custom notification handler
[self handleLocalNotification:lastNotification];
}
}

Execute method if user cancel the UILocaNotification alert in iPhone SDK

I am new to iphone Programming . I am using localNotification in my application.It is giving alert to user and responding to Launch using didReceiveLocalNotification.But my problem is if user close the UILocalNotification in my Application i need to execute database operation .So how can i do that .Is there any approach for that one.
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
NSDate* now = [NSDate date];
[localNotification setFireDate:now];
localNotification.soundName=#"Tink.wav";
[localNotification setAlertAction:#"Launch"];
[localNotification setAlertBody:#"You have entered to Your Place:"];
[localNotification setHasAction: YES];
NSDictionary *userDict = [NSDictionary dictionaryWithObject:#"obj" forKey:kRemindMeNotificationDataKey];
localNotification.userInfo = userDict;
- (void)application:(UIApplication *)app didReceiveLocalNotification:(UILocalNotification *)notif {
NSLog(#"Recieved Notification");
NSString *DateString=[notif.userInfo valueForKey:kRemindMeNotificationDataKey];
if([DateString isEqualToString:#"obj"])
{
[[UIApplication sharedApplication] cancelLocalNotification:notif];
}
NSString *strNotif=[notif.userInfo objectForKey:kRemindMeNotificationDataKey];
if ([strNotif isEqualToString:#"obj"]) {
UIAlertView *alretCheck=[[UIAlertView alloc]initWithTitle:#"notifi Testing in DidRec+" message:strNotif delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alretCheck show];
[alretCheck release];
}
Thanking you in advance.
Now Acc. to my Knowledge we cannot do that what you want. we only have command on the "View" Option of LocalNotification Alert. But if possible u can do one thing onClick on "View" button u can Show an ActionSheet or another alert and on those buttons you can handle all the event you want.

how to set uilocalnotification firedate for a fixed date?

i want to set localnotification say for a program which starts at 6:00 pm.For that i have taken the time in a date variable and i am comparing it with current date from system.
Say setDate is for fixed date i.e 6.00 pm so i have to set firedate such that it shows the notification before 30 mintes the program starts. The examples i have seen in that the firedate is set according to currentdate.
Can someone tell me how can i set firedate according to my fixed date??
You fire the local notification this way
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
if (localNotif == nil)
return;
localNotif.fireDate = [NSDate date];// Now here you can manage the fire time.
localNotif.timeZone = [NSTimeZone defaultTimeZone];
// Notification details
localNotif.alertBody = #"BusBuddy";
// Set the action button
localNotif.alertAction = #"View";
localNotif.soundName = UILocalNotificationDefaultSoundName;
localNotif.applicationIconBadgeNumber = 1;
// Specify custom data for the notification
NSDictionary *infoDict = [NSDictionary dictionaryWithObject:#"You are near to reach the Bus Stop" forKey:#"someKey"];
localNotif.userInfo = infoDict;
// Schedule the notification
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
[localNotif release];
This line of code will work for you. you just need to provide the date time for this
localNotif.fireDate = [NSDate date];
And now for formatting your date time you can refer to these links
iphonedevelopertips.com
developer.apple.com, CFDatesAndTimes
developer.apple.com, DataFormatting
Well then you can handle your local notification in application delegate file when ever you get the notification.
e.g. here is the delegate method which is fired everytime when you get the local notification.
- (void)application:(UIApplication *)app didReceiveLocalNotification:(UILocalNotification *)notif {
//Handle the notificaton when the app is running
NSLog(#"Recieved Notification %#",notif);
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Hey Neha" message:#"Sanjay wants to be your friend " delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alertView show];
[alertView release];
SystemSoundID bell;
AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"WhoopFlp" ofType:#"wav"]], &bell);
AudioServicesPlaySystemSound (bell);
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
i=0;
}
}
So what I am doing here is simply showing the alert and playing a system sound when my local notification occurs.
So now what you want is to navigate to the page in the program where you were when you get the local notification.So simply in this delegate method you need to allocate your view controller and need to push the view controller to that view where you want to be.
That would solve your problem.
Well i had a similar kind of problem what i wanted is to show the notification in the background and in the front end as well, so writing the 2 different methods in my app was not worthful.so i handled it this way in the delegate method which will show the notification in the front end as well.
Good luck to you.
localnotification =[[UILocalNotification alloc]init];
[localnotification setFireDate:[NSDate dateWithTimeIntervalSinceNow:[lodatepicker countDownDuration]]];
[localnotification setAlertAction:#"Launch"];
[localnotification setHasAction: YES];
[localnotification setAlertBody:[lotextview text]];
// [localnotification setSoundName:musicString];
localnotification.timeZone = [NSTimeZone defaultTimeZone];
[localnotification setApplicationIconBadgeNumber:[[UIApplication sharedApplication] applicationIconBadgeNumber]+1];
[[UIApplication sharedApplication] scheduleLocalNotification:localnotification];