Objective-C:带有提醒的应用程序即使在应用程序被终止或 phone 重新启动时也能正常工作
Objective-C: App with a reminder that will work even when app is killed or phone is restarted
在下面的代码中,我设法每 15 秒触发我的 checkSchedule
方法(出于测试目的),checkSchedule
将发送一个 API 然后检查是否有任何约会.如果connectionFinishLoading
检测到结果,会通知用户
如果应用程序在前台或后台,当前代码将起作用。
但是,我希望在应用程序被终止或 phone 重新启动并且应用程序未启动时让它工作。基本上,该功能类似于Any.do
app(提醒应用程序),即使应用程序被杀死或phone 重新启动也会触发提醒。非常感谢任何指点或帮助。
@AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self startTimerLoop];
return YES;
}
//==== This loop will run every hour and call Check Schedule,
//==== It will break the 3 min barrier
-(void)startTimerLoop{
//NSLog(@"Hi I am in the timer .. %@ ", [NSDate date]);
[objTimer invalidate];
objTimer = nil;
//===repeat every 15 secs for testing purposes
bgTask = UIBackgroundTaskInvalid;
UIApplication *app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{}];
objTimer = [NSTimer scheduledTimerWithTimeInterval:15 target:self selector:@selector(checkSchedule) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:objTimer forMode:UITrackingRunLoopMode];
}
//=== Check from 2 hours from now if there is any classes
//=== it will send and web API and is it return a result,
//=== it will notify the user
-(void)checkSchedule{
//=== Initialize the responseData Mutable Data
self.responseData = [NSMutableData data];
//=== Call the stored txtMemCode, something like session ---
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *sMemCode = [defaults objectForKey:@"txtMemCode"];
NSDate *now = [NSDate date];
NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init];
[outputFormatter setDateFormat:@"HH:mm"];
NSString *sTime = [outputFormatter stringFromDate:now];
sTime = [sTime stringByReplacingOccurrencesOfString:@":" withString:@"%3A"];
//====Check from 2 hours from now====
NSTimeInterval secInTwoHours = 2*60*60; //=== sec in 2 hours
NSDate *twoHoursAhead = [now dateByAddingTimeInterval:secInTwoHours];
NSString *sTime2Hours = [outputFormatter stringFromDate:twoHoursAhead];
sTime2Hours = [sTime2Hours stringByReplacingOccurrencesOfString:@":" withString:@"%3A"];
if (sMemCode != nil) {
//=== Pass the string to web and get the return State response.write
sURL = gURL;
sURL = [sURL stringByAppendingString:@"/apps/checkBooking.asp?"];
sURL = [sURL stringByAppendingString:@"memCode="];
sURL = [sURL stringByAppendingString:sMemCode];
sURL = [sURL stringByAppendingString:@"&tocheck="];
sURL = [sURL stringByAppendingString:sTime];
sURL = [sURL stringByAppendingString:@"&tocheck2="];
sURL = [sURL stringByAppendingString:sTime2Hours];
NSLog(@" The sURL : %@ ", sURL);
NSURLRequest *requestState = [NSURLRequest requestWithURL:[NSURL URLWithString:sURL]];
(void) [[NSURLConnection alloc] initWithRequest:requestState delegate:self];
}
}
//=== This getting the return results from the called API.
//=== If there is a result, it will notify the user.
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(@"connectionDidFinishLoading");
NSLog(@"=========Succeeded! Received %d bytes of data",[self.responseData length]);
NSString *sResponseData = [[NSString alloc] initWithData:self.responseData encoding:NSUTF8StringEncoding];
NSLog(@"=======*************** This Response.write stuff %@", sResponseData);
NSString *sSeparator= @"|";
NSRange range = [sResponseData rangeOfString:sSeparator];
NSInteger position = range.location + range.length;
NSString *sRecords = [sResponseData substringToIndex:position-1];
NSString *sRemaining = [sResponseData substringFromIndex:position];
if ([sRecords isEqualToString:@"0"]){
NSLog(@" There is no classes ");
}else {
range = [sRemaining rangeOfString:sSeparator];
position = range.location + range.length;
NSString *sMessage = [sRemaining substringToIndex:position-1];
NSString *sTime = [sRemaining substringFromIndex:position];
NSString *sBody = sMessage;
sBody = [sBody stringByAppendingString:@" "];
sBody = [sBody stringByAppendingString:sTime];
UNMutableNotificationContent* content = [[UNMutableNotificationContent alloc] init];
content.title = [NSString localizedUserNotificationStringForKey:@"Class Reminder!"
arguments:nil];
content.body = [NSString localizedUserNotificationStringForKey:sBody
arguments:nil];
content.sound = [UNNotificationSound defaultSound];
UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:1 repeats:NO];
UNNotificationRequest *notificationRequest = [UNNotificationRequest requestWithIdentifier:@"NotificationIdentifier" content:content trigger:trigger];
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center addNotificationRequest:notificationRequest
withCompletionHandler:^(NSError * _Nullable error) {
NSLog(@"completed!");
}];
}
[[UIApplication sharedApplication] endIgnoringInteractionEvents];
}
必须按照 Firebase 的说明设置远程通知。
// Handle incoming notification messages while app is in the foreground.
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
// Print message ID.
NSDictionary *userInfo = notification.request.content.userInfo;
if (userInfo[kGCMMessageIDKey]) {
NSLog(@"**3 : Message ID: %@", userInfo[kGCMMessageIDKey]);
}
// Print full message.
NSLog(@" **4 : %@", userInfo);
//==== This will show the notification while APP is in the foreground
completionHandler(UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge);
//completionHandler(UNNotificationPresentationOptionNone);
}
在下面的代码中,我设法每 15 秒触发我的 checkSchedule
方法(出于测试目的),checkSchedule
将发送一个 API 然后检查是否有任何约会.如果connectionFinishLoading
检测到结果,会通知用户
如果应用程序在前台或后台,当前代码将起作用。
但是,我希望在应用程序被终止或 phone 重新启动并且应用程序未启动时让它工作。基本上,该功能类似于Any.do
app(提醒应用程序),即使应用程序被杀死或phone 重新启动也会触发提醒。非常感谢任何指点或帮助。
@AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self startTimerLoop];
return YES;
}
//==== This loop will run every hour and call Check Schedule,
//==== It will break the 3 min barrier
-(void)startTimerLoop{
//NSLog(@"Hi I am in the timer .. %@ ", [NSDate date]);
[objTimer invalidate];
objTimer = nil;
//===repeat every 15 secs for testing purposes
bgTask = UIBackgroundTaskInvalid;
UIApplication *app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{}];
objTimer = [NSTimer scheduledTimerWithTimeInterval:15 target:self selector:@selector(checkSchedule) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:objTimer forMode:UITrackingRunLoopMode];
}
//=== Check from 2 hours from now if there is any classes
//=== it will send and web API and is it return a result,
//=== it will notify the user
-(void)checkSchedule{
//=== Initialize the responseData Mutable Data
self.responseData = [NSMutableData data];
//=== Call the stored txtMemCode, something like session ---
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *sMemCode = [defaults objectForKey:@"txtMemCode"];
NSDate *now = [NSDate date];
NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init];
[outputFormatter setDateFormat:@"HH:mm"];
NSString *sTime = [outputFormatter stringFromDate:now];
sTime = [sTime stringByReplacingOccurrencesOfString:@":" withString:@"%3A"];
//====Check from 2 hours from now====
NSTimeInterval secInTwoHours = 2*60*60; //=== sec in 2 hours
NSDate *twoHoursAhead = [now dateByAddingTimeInterval:secInTwoHours];
NSString *sTime2Hours = [outputFormatter stringFromDate:twoHoursAhead];
sTime2Hours = [sTime2Hours stringByReplacingOccurrencesOfString:@":" withString:@"%3A"];
if (sMemCode != nil) {
//=== Pass the string to web and get the return State response.write
sURL = gURL;
sURL = [sURL stringByAppendingString:@"/apps/checkBooking.asp?"];
sURL = [sURL stringByAppendingString:@"memCode="];
sURL = [sURL stringByAppendingString:sMemCode];
sURL = [sURL stringByAppendingString:@"&tocheck="];
sURL = [sURL stringByAppendingString:sTime];
sURL = [sURL stringByAppendingString:@"&tocheck2="];
sURL = [sURL stringByAppendingString:sTime2Hours];
NSLog(@" The sURL : %@ ", sURL);
NSURLRequest *requestState = [NSURLRequest requestWithURL:[NSURL URLWithString:sURL]];
(void) [[NSURLConnection alloc] initWithRequest:requestState delegate:self];
}
}
//=== This getting the return results from the called API.
//=== If there is a result, it will notify the user.
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(@"connectionDidFinishLoading");
NSLog(@"=========Succeeded! Received %d bytes of data",[self.responseData length]);
NSString *sResponseData = [[NSString alloc] initWithData:self.responseData encoding:NSUTF8StringEncoding];
NSLog(@"=======*************** This Response.write stuff %@", sResponseData);
NSString *sSeparator= @"|";
NSRange range = [sResponseData rangeOfString:sSeparator];
NSInteger position = range.location + range.length;
NSString *sRecords = [sResponseData substringToIndex:position-1];
NSString *sRemaining = [sResponseData substringFromIndex:position];
if ([sRecords isEqualToString:@"0"]){
NSLog(@" There is no classes ");
}else {
range = [sRemaining rangeOfString:sSeparator];
position = range.location + range.length;
NSString *sMessage = [sRemaining substringToIndex:position-1];
NSString *sTime = [sRemaining substringFromIndex:position];
NSString *sBody = sMessage;
sBody = [sBody stringByAppendingString:@" "];
sBody = [sBody stringByAppendingString:sTime];
UNMutableNotificationContent* content = [[UNMutableNotificationContent alloc] init];
content.title = [NSString localizedUserNotificationStringForKey:@"Class Reminder!"
arguments:nil];
content.body = [NSString localizedUserNotificationStringForKey:sBody
arguments:nil];
content.sound = [UNNotificationSound defaultSound];
UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:1 repeats:NO];
UNNotificationRequest *notificationRequest = [UNNotificationRequest requestWithIdentifier:@"NotificationIdentifier" content:content trigger:trigger];
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center addNotificationRequest:notificationRequest
withCompletionHandler:^(NSError * _Nullable error) {
NSLog(@"completed!");
}];
}
[[UIApplication sharedApplication] endIgnoringInteractionEvents];
}
必须按照 Firebase 的说明设置远程通知。
// Handle incoming notification messages while app is in the foreground.
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
// Print message ID.
NSDictionary *userInfo = notification.request.content.userInfo;
if (userInfo[kGCMMessageIDKey]) {
NSLog(@"**3 : Message ID: %@", userInfo[kGCMMessageIDKey]);
}
// Print full message.
NSLog(@" **4 : %@", userInfo);
//==== This will show the notification while APP is in the foreground
completionHandler(UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge);
//completionHandler(UNNotificationPresentationOptionNone);
}