我正在开发一款需要在iOS4后台运行的应用。一世 希望它像常规的基于位置的应用程序,所以BackgroundMode是 设置为位置。应用程序进入后台时效果很好 状态,但10分钟后,它停止响应。也许吧 被暂停/终止。 我想要做的是永远在后台运行应用程序 在用户终止申请之前没有任何时间限制 只。请指导我如何实现这一目标。 在GPS更新到新位置时,我会弹出本地通知。这里提供了一些代码:
- (void)applicationDidEnterBackground:(UIApplication *)application {
/*
Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
If your application supports background execution, called instead of applicationWillTerminate: when the user quits.
*/
UIApplication* app = [UIApplication sharedApplication];
// Request permission to run in the background. Provide an
// expiration handler in case the task runs long.
NSAssert(bgTask == UIBackgroundTaskInvalid, nil);
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
// Synchronize the cleanup call on the main thread in case
// the task actually finishes at around the same time.
dispatch_async(dispatch_get_main_queue(), ^{
if (bgTask != UIBackgroundTaskInvalid)
{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}
});
}];
// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Do the work associated with the task.
locmanager = [[CLLocationManager alloc] init];
[locmanager setDelegate:self];
[locmanager setDesiredAccuracy:kCLLocationAccuracyBest];
locmanager.distanceFilter = 20;
[locmanager startUpdatingLocation];
NSLog(@"App staus: applicationDidEnterBackground");
// Synchronize the cleanup call on the main thread in case
// the expiration handler is fired at the same time.
dispatch_async(dispatch_get_main_queue(), ^{
if (bgTask != UIBackgroundTaskInvalid)
{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}
});
});
NSLog(@"backgroundTimeRemaining: %f", [[UIApplication sharedApplication] backgroundTimeRemaining]);
}
and
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
// Log the kind of accuracy we got from this
NSLog(@"Accuracy-------- %f %f", [newLocation horizontalAccuracy], [newLocation verticalAccuracy]);
CLLocationCoordinate2D loc = [newLocation coordinate];
userCurrentLocation = newLocation;
lat = loc.latitude;
lon = loc.longitude;
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
if (localNotif == nil)
return;
NSDate *now = [NSDate dateWithTimeIntervalSinceNow:10];
NSLog(@"Now is %@",now);
localNotif.fireDate = now;
localNotif.timeZone = [NSTimeZone defaultTimeZone];
// Notification details
localNotif.alertBody = [NSString stringWithFormat:@"Latitude = %f, Longitude = %f", lat, lon];
// Set the action button
localNotif.alertAction = @"View";
localNotif.soundName = UILocalNotificationDefaultSoundName;
localNotif.applicationIconBadgeNumber = 1;
// Specify custom data for the notification
NSDictionary *infoDict = [NSDictionary dictionaryWithObject:@"someValue" forKey:@"someKey"];
localNotif.userInfo = infoDict;
// Schedule the notification
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
[localNotif release];
}
Plz指导我如何做到这一点?
答案 0 :(得分:3)
你的info.plist包含这些内容吗?
应用程序可以将自己声明为连续的后台位置应用程序。需要标准位置服务提供的常规位置更新的应用程序可以将其自身声明为连续后台应用程序。它通过在其Info.plist文件中包含UIBackgroundModes键并将此键的值设置为包含位置字符串的数组来完成此操作。如果具有此密钥的应用程序在进入后台时运行位置服务,则系统不会挂起该服务。相反,它允许继续运行,以便它可以在后台执行与位置相关的任务。
答案 1 :(得分:1)
您不需要执行beginBackgroundTask ...(事实上您不应该),通过注册位置更新(请参阅上面的帖子),您的应用程序将自动被唤醒并通知位置更改。后台任务是出于另一个目的(扩展下载等),你只有有限的时间来完成它们(大约10分钟),如果你试图让后台任务打开的时间更长,你的应用程序将被终止。
基本上摆脱了beginBackgroundTask的东西,并添加了UIBackgroundModes - > info.plist的位置键,以便您注册即使在后台也可以通知您的应用位置更改。