I have a multiple local notification which repeat every minutes.when local notification are arrive then i update the database.It's Work fine. But when we set multiple notification then It's fire time is Same.so both local notification simultaneously execute at same time.*This situation into my database update is not work properly.means first value reference data are updated *
//below set notification.
AlarmNotification = [[UILocalNotification alloc]init];
// AlarmNotification.fireDate = SetAlarmTime;
AlarmNotification.fireDate = AddMinutes;
AlarmNotification.repeatInterval = NSMinuteCalendarUnit;
AlarmNotification.alertBody =cloclListInsert.labelText;
AlarmNotification.timeZone = [NSTimeZone defaultTimeZone];
AlarmNotification.soundName =cloclListInsert.SelctAlaemToneDbStr;
NSMutableDictionary *userDict = [[NSMutableDictionary alloc] init];
NSString *ClockIDStr = [NSString stringWithFormat:#"%i",cloclListInsert.ClockIDvalue];
[userDict setObject:ClockIDStr forKey:#"ClockID"];
AlarmNotification.userInfo = userDict;
[[UIApplication sharedApplication]scheduleLocalNotification:AlarmNotification];
delegate method in App Delegate
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
NSLog(#"notification.userInfo : %#",notification.userInfo);
NSString *SelectID= [notification.userInfo objectForKey:#"ClockID"];
NSLog(#"SelectID is : %#",SelectID);
NSLog(#"notification.userInfo : %#",notification.userInfo);
NotificationId = [SelectID integerValue];
NSLog(#"NotificationId is : %i",NotificationId);
clocklistobj.ClockIDvalue = NotificationId;
if ([sqldbobj getNotificationClockList:clocklistobj]) {
NotificationCount = clocklistobj.incrementTag;
NSLog(#"NotificationCount : %i",NotificationCount);
clocklistobj.incrementTag =NotificationCount +1;
//insert increment tag in counter variable
counter = clocklistobj.incrementTag;
NSLog(#"counter when receive notification in delegate method: %i",counter);
NSLog(#"NotificationCount +1 & clocklistobj.incrementTag : %i",clocklistobj.incrementTag);
//set brightness of device
SetBrightnessValue = (float) (clocklistobj.incrementTag *0.066666);
NSLog(#"SetBrightnessValue : %f",SetBrightnessValue);
[[UIScreen mainScreen] setBrightness:SetBrightnessValue];
//set music player & control volume
setPlayerVolume = (float) (clocklistobj.incrementTag *0.066666);
NSLog(#"set Player Volume : %f",setPlayerVolume);
[audioPlayer setVolume:setPlayerVolume];
//below start playing audio
[audioPlayer play];
//update database
[sqldbobj UpdateNotificationCount:clocklistobj];
NSLog(#" After update clocklistobj.incrementTag:%i",clocklistobj.incrementTag);
if (clocklistobj.incrementTag ==15 || clocklistobj.incrementTag >15) {
NSLog(#"Notification reach at limit");
UIApplication *app = [UIApplication sharedApplication];
NSArray *eventArray = [app scheduledLocalNotifications];
// NSLog(#"eventArray : %#",eventArray);
for (int i=0; i<[eventArray count]; i++)
{
UILocalNotification* oneEvent = [eventArray objectAtIndex:i];
NSDictionary *userInfoCurrent = oneEvent.userInfo;
NSString *uid=[NSString stringWithFormat:#"%#",[userInfoCurrent valueForKey:#"ClockID"]];
NSInteger GetUid = [uid integerValue];
//here we cancell the particular notification
NSLog(#"Application is stoped clocklistobj.ClockIDvalue : %i", clocklistobj.ClockIDvalue);
if (GetUid ==clocklistobj.ClockIDvalue)
{
clocklistobj.soundisON = 0;
[sqldbobj UpdateAfteNotificationSwitchMakeOff:clocklistobj];
//Cancelling local notification
[app cancelLocalNotification:oneEvent];
break;
}
}
}else {
NSLog(#"Notification is off");
}
}
}
Ok so what you can do is you can restrict the user from setting multiple alarm at the same time.
For doing so you have to call [[UIApplication sharedApplication] scheduledLocalNotifications], it will provide you all the notifications scheduled till now.
Then you can go through these notification and check for the notification.fireDate if it matches your current scheduling fireDate then you can show an alert to user by saying that 'There is another alarm scheduled at the same time.'.
Related
I can't seem to find it and I'm not sure how to Google it. In my app I use background fetches to do checks and if there is new data, I send a notification to the user using UILocalNotification. Now how do I prevent the app from sending a new notification to the user if there is already one there? I'm now ending up with 5 of the same notifications when I don't look at my phone for some hours.
Thanks!
You can use UIApplication's property scheduledLocalNotifications
Here's the sample code:
NSMutableArray *notifications = [[NSMutableArray alloc] init]; [notifications addObject:notification]; myApp.scheduledLocalNotifications = notifications;
//Equivalent: [myApp setScheduledLocalNotifications:notifications];
UIApplication *myApp = [UIApplication sharedApplication];
NSArray *eventArray = [myApp scheduledLocalNotifications];
for (int i=0; i<[eventArray count]; i++)
{
UILocalNotification* oneEvent = [eventArray objectAtIndex:i];
NSDictionary *userInfoCurrent = oneEvent.userInfo;
NSString *uid=[NSString stringWithFormat:#"%#",[userInfoCurrent valueForKey:#"uid"]];
if ([uid isEqualToString:uidtodelete])
{
//Cancelling local notification
[myApp cancelLocalNotification:oneEvent];
break;
}
}
NSArray *arrayOfLocalNotifications = [[UIApplication sharedApplication] scheduledLocalNotifications] ;
for (UILocalNotification *localNotification in arrayOfLocalNotifications) {
if ([localNotification.alertBody isEqualToString:savedTitle]) {
NSLog(#"the notification this is canceld is %#", localNotification.alertBody);
[[UIApplication sharedApplication] cancelLocalNotification:localNotification] ; // delete the notification from the system
}
}
Hope this would help figure out the solution.
The best way to avoid having to cancel something it in the first place is also to simply NOT sending it.
Find a way to know if the user has been notified before, and if he has, don't notify again :)
This is cleaner, more efficient, will last forever, and won't backfire, ever.
Also, this answers your question of "not sending a notification again" instead of sending it and cancelling afterwards, which isn't a good idea if you think about it.
I'm currently trying to cancel specific UILocalNotifications associated with objects in my data model. To do this, each data object has a unique identifier, which is an NSUUID.
Create UILocalNotification:
/* Set UILocalNotification */
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.fireDate = date;
localNotification.alertBody = self.mytextfield.text;
localNotification.soundName = UILocalNotificationDefaultSoundName;
localNotification.applicationIconBadgeNumber = 1;
NSLog(#"making a notification: %#",[r.uniqueId UUIDString]);
[localNotification.userInfo setValue:[r.uniqueId UUIDString] forKey:#"uid"];
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
Yet when I go to delete the notification and print out each notifications contents, the alertbody of the notifications are printed correctly but the unique identifier is somehow lost. What's wrong with this implementation?
Cancel UILocalNotification:
Obj *r = (Obj *)[self.objects[indexPath.section] objectAtIndex:indexPath.row];
/* Cancel UILocalNotification */
NSArray *scheduleReminders = [[UIApplication sharedApplication] scheduledLocalNotifications];
NSLog(#"scheduled.count: %i",(int)scheduleReminders.count); // Correctly prints 3
for (int i = 0; i < scheduleReminders.count; i++)
{
UILocalNotification *notification = scheduleReminders[i];
NSDictionary *userInfoCurrent = notification.userInfo;
NSLog(#"searching through reminders: %i %# %# %#",(int)i,[userInfoCurrent objectForKey:#"uid"], notification.alertBody); // Alert body prints correctly
if ([[userInfoCurrent valueForKey:#"uid"] isEqualToString:[r.uniqueId UUIDString]])
{
NSLog(#"found it");
//Cancelling local notification
[[UIApplication sharedApplication] cancelLocalNotification:notification];
break;
}
}
The problem is that userInfo is "nil" by default. You should allocate your own NSDictionary, set uid and then set this dictionary to localNotification.userInfo.
I want to schedule local notification in my game.
First notification will come two hours after game play has ended.
After that another one come in the next 24 hours if still no gameplay. If gameplay resets to after 2 hours, then every 24 hrs until they enter game.
I would be very thankful to you if you can help me.
Here is my code:
UILocalNotification *notif = [[UILocalNotification alloc] init];
notif.alertBody = [self.notifyArray objectAtIndex:index];
NSTimeInterval sec = 7200;
notif.fireDate = [NSDate dateWithTimeIntervalSinceNow:sec];
notif.repeatInterval = NSDayCalendarUnit;
notif.soundName = UILocalNotificationDefaultSoundName;
NSLog(#"notif : %u",notif.repeatInterval);
notif.applicationIconBadgeNumber += 1;
[[UIApplication sharedApplication] scheduleLocalNotification:notif];
//notif.fireDate = [NSDate dateWithTimeIntervalSinceNow:20];
//[[UIApplication sharedApplication] scheduleLocalNotification:notif];
Try to debug first by checking the scheduled notifications list. You can see this thread for details iOS find list of Local Notification the app has already set
First give an 'identifier' to your local notification. Then and when app goes to background, use that identifier to identify notification from scheduled notifications of your application. And reschedule it after 2 hours , with repeat interval of day.
UIApplication *app = [UIApplication sharedApplication];
NSArray *eventArray = [app scheduledLocalNotifications];
for (int i=0; i<[eventArray count]; i++)
{
UILocalNotification* oneEvent = [eventArray objectAtIndex:i];
if ( oneEvent.identifier = yourNotificationIdentifier){
//Reschedule oneEvent.
}
}
I'm using a UILocalNotification object to give notification to my application. Currently each time an event is generated i popup a notification.
notification.alertBody=#"Event Occurs 2";
notification.alertAction=#"Open";
[[UIApplication sharedApplication]presentLocalNotificationNow:notification];
But, since the events keep on happening, each time a new notification is generated.
Is there a way to update a notification, if it is already present and create a new notification if not present.
You can't update an already scheduled Local Notication. You can however, cancel it and reschedule a new one.
Cancel your local notification:
UIApplication *app = [UIApplication sharedApplication];
NSArray *eventArray = [app scheduledLocalNotifications];
for (int i=0; i<[eventArray count]; i++)
{
UILocalNotification* oneEvent = [eventArray objectAtIndex:i];
NSDictionary *userInfoCurrent = oneEvent.userInfo;
NSString *uid=[NSString stringWithFormat:#"%#",[userInfoCurrent valueForKey:#"uid"]];
if ([uid isEqualToString:uidtodelete])
{
//Cancelling the specific local notification
[app cancelLocalNotification:oneEvent];
//Schedule your new "updated" local notification here.
break;
}
}
This will loop through all scheduled local notifications and delete the local notification you want deleted. Note, you'll need to set a unique property to each notification to distinguish between others (in the example above, it is assumed userInfo contains a unique "uid").
Thanks to KingofBliss for code above on how to delete specific local notifications.
It's not possible to update the notification but if you attach a dictionary with a key to the alert:
UILocalNotification *notification = [[UILocalNotification alloc] init];
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
[userInfo setObject:alarmID forKey:#"AlarmKey"];
// Set some extra info to your alarm
notification.userInfo = userInfo;
Then you can retrieve the local notification, cancel it and make a new one with updated content.
+ (UILocalNotification *)existingNotificationWithAlarmID:(NSString *)alarmID
{
for (UILocalNotification *notification in [[UIApplication sharedApplication] scheduledLocalNotifications]) {
if ([[notification.userInfo objectForKey:#"AlarmKey"] isEqualToString:alarmID]) {
return notification;
}
}
return nil;
}
You cancel the notification like this:
- (void)cleanUpLocalNotificationWithAlarmID:(NSString *)alarmID
{
UILocalNotification *notification = [self existingNotificationWithAlarmID:alarmID];
if (notification) {
[[UIApplication sharedApplication] cancelLocalNotification:notification];
}
}
No, there is no way to modify a local notification that has been scheduled. You'll have to cancel the notification and schedule it again.
I have an app where I need to send a UILocationNotification when the app is not in the foreground / Active. If I have my code to do so, it will not send until the app is opened and is active.
Here is my function:
- (void)setLocalNotificationForType:(SPKLocalNotificationType)notificationType fromUser:(NSString *)userName withMessageText:(NSString *)msgText {
UILocalNotification *notif = [[UILocalNotification alloc] init];
notif.userInfo = #{#"handle": _convoHandle, #"room": _convoName};
notif.fireDate = [NSDate date];
notif.applicationIconBadgeNumber = [[UIApplication sharedApplication] applicationIconBadgeNumber] + 1;
notif.soundName = UILocalNotificationDefaultSoundName;
notif.timeZone = [NSTimeZone defaultTimeZone];
if (notificationType == 1) { // message
notif.alertBody = [NSString stringWithFormat:#"#%# said: \"%#\"", userName, msgText];
} else if (notificationType == 2) { // image
notif.alertBody = [NSString stringWithFormat:#"#%# sent an image", userName];
} else {
return;
}
if ([[UIApplication sharedApplication] applicationState] != UIApplicationStateActive) {
[[UIApplication sharedApplication] presentLocalNotificationNow:notif];
}
}
Update:
It now seems that the problem is that the connection to the server is being "paused" while the app is in the background. Once I then open the app all the data comes in at once. I am using SocketRocket for connecting to my Node.js Primus web socket server. Is this something that normally happens? This is my first time using SocketRocket so I'm not sure.
Update:
I have also enabled Remote Notifications for Background Modes, I have also registered for remote notifications, and on the device, I have also made sure that "banners" and "badges" are enabled.
Update:
I have additionally set the web socket to use a background queue.
[webSocket setDelegateOperationQueue:[NSOperationQueue new]];
The connection is still being paused.
Thanks!
Edit: It looks like SocketRocket uses the main dispatch queue by default, which runs on the application's main thread. When the app is backgrounded, processing on the main thread stops, so it would be worth trying to move the work to a background thread in a background operation queue.
On your SRWebSocket object, try calling:
[webSocket setDelegateOperationQueue:[NSOperationQueue new]];
Without checking the docs, perhaps setting timeZone and fireDate on the UILocalNotification is interfering. You don't need those if you're going to pass the notification to presentLocalNotificationNow:.
I have also found that, even if you're using local notifications exclusively, you must:
Enable Remote notifications for your target on the Capabilities tab under Background Modes
Enable either alerts or banners in the Settings app, in Notification Center settings.
A sample event handler for a background fetch:
- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
UIBackgroundFetchResult result = UIBackgroundFetchResultNoData;
// ... perform a network request
if (successfulNetworkRequest) {
UILocalNotification* localNotification = [UILocalNotification new];
localNotification.alertAction = #"View";
localNotification.alertBody = #"Stuff";
localNotification.soundName = UILocalNotificationDefaultSoundName;
localNotification.applicationIconBadgeNumber = 1;
localNotification.userInfo = #{#"stuff": #"other stuff"};
[application presentLocalNotificationNow:localNotification];
result = UIBackgroundFetchResultNewData;
} else {
result = UIBackgroundFetchResultFailed;
}
completionHandler(result);
}
I am afraid you are misunderstanding of local notification. I guess what you should do is registering a notification in the future and send it some time after user clicked the home button. But in your code, you registered a alert in CURRENT TIME and did some thing on the notification (sorry but I don't know what you want to do in your code).
You could change it like this to make a sense:
- (void)setLocalNotificationForType:(SPKLocalNotificationType)notificationType fromUser:(NSString *)userName withMessageText:(NSString *)msgText {
UILocalNotification *notif = [[UILocalNotification alloc] init];
notif.userInfo = #{#"handle": _convoHandle, #"room": _convoName};
//Set the fire time 10 seconds later
notif.fireDate = [[NSDate date] dateByAddingTimeInterval:10];
notif.applicationIconBadgeNumber = [[UIApplication sharedApplication] applicationIconBadgeNumber] + 1;
notif.soundName = UILocalNotificationDefaultSoundName;
notif.timeZone = [NSTimeZone defaultTimeZone];
if (notificationType == 1) { // message
notif.alertBody = [NSString stringWithFormat:#"#%# said: \"%#\"", userName, msgText];
} else if (notificationType == 2) { // image
notif.alertBody = [NSString stringWithFormat:#"#%# sent an image", userName];
} else {
return;
}
//Register this notification
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
}
And in your app delegate's -applicationDidEnterBackground:, call your -setLocalNotificationForType:fromUser:withMessageText: method to make and register a notification. Then you can expect a local notification 10s after you click the home button.