一、 关于本地通知
本地通知,就是应用完成某个任务的时候发送一些提示。在APP打开的情况下,如果不对本地通知做任何界面显示的话,那么看不到界面有任何变化。如果用户点击Home以后,App在后台有3分钟的运行时间的话(即App在后台运行),那么本地通知就会以信息提示栏的形式显示在手机上面,和离线消息推送的效果一样。。如果用户点击Home以后,你的App处于挂起状态,那个发送了的本地通知并不是说永远不会执行了,而是当前你的重新进入应用以后,它还会继续执行。
二、遇到的问题
我的App对本地通知的处理要求:
1.当用户点击Home键以后,App有大概3分钟的后台运行时间。
2.如果用户正在使用App,当有本地通知时,以Alert的形式显示出来。
3.如果用户在使用App的时候点击了Home键,在3分钟内如果有通知到来,那么需要在通知栏中显示本地通知内容。
在实现以上需求时遇到的问题:
当用户点击Home键,在3分钟内有本地通知到达时,如果等本地通知的通知栏消失时,再通过点击app的图标进入app则一切正常。但是,如果点击通知栏进入App时,会有Alert消息弹出来,即本地通知显示了两次。
三、解决方法
把App的状态分为前台(InForeground)和后台(InBackground)两种情况,当发送本地通知的时候,把App的状态作为一个value保存在通知的userInfo字典中。在AppDelegate中判断接收的通知是app在前台发送的还是在后台发送的,如果是在前台发送的,则正常显示alert信息,如果是在后台发送的,那么就直接return。
四、代码
发送通知的代码:
/**
* Post a local notification
*
* @param info info notification content
* @param time How many seconds after sending notification.
* @param isBackground YES:app run in background NO:app run in foreground.
*/
+ (void)postLocalNotificationWithInfo:(NSString *)info andTimeSinceNow:(NSInteger)time inBackground:(BOOL)isBackground
{
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:time];
localNotification.timeZone = [NSTimeZone defaultTimeZone];
localNotification.alertBody = info;
localNotification.applicationIconBadgeNumber = [[UIApplication sharedApplication] applicationIconBadgeNumber] + 1;
localNotification.soundName = UILocalNotificationDefaultSoundName;
NSMutableDictionary *userDict = [NSMutableDictionary dictionaryWithObject:info forKey:@"localNofiKey"];
isBackground ? [userDict setValue:@"inBackground" forKey:@"AppStatus"] : [userDict setValue:@"inForeground" forKey:@"AppStatus"];
localNotification.userInfo = userDict;
if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)]) {
UIUserNotificationType type = UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound;
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:type
categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
}
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
}
AppDelegate中对本地通知处理的代码:
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
NSString *statusApp = [notification.userInfo objectForKey:@"AppStatus"];
if ([statusApp isEqualToString:@"inBackground"]) {
return;
}
NSString *nofiInfo = [notification.userInfo objectForKey:@"localNofiKey"];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Upload Message"
message:nofiInfo
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
dispatch_time_t dismissTime = dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC);
dispatch_after(dismissTime, dispatch_get_main_queue(), ^{
[alert dismissWithClickedButtonIndex:1 animated:YES];
});
[alert release];
}
注意:至于如何判断App是在前台还是在后台,我们可以声明一个int变量,0是后台,1是前台。则通过在AppDelegate中的几个方法中设置这个变量的值。然后在需要发送通知的地方外部引用该变量。