xcode 在后台运行的 iPhone 应用程序在 10 分钟后终止

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3775730/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 19:46:40  来源:igfitidea点击:

iPhone App runnung in the background terminates after 10 minutes

iphoneobjective-cxcode

提问by engr.rf4u

I am working on an app that needs to run in the background on iOS4. I want it to be a like regular Location-based app so the BackgroundMode is set to location. The application works well when it enters the background state but after 10 minutes, it stops responding anymore. Perhaps it gets suspended/terminated. What I want to do is run the application in the background forever without any time limit until the user terminates the application exclusively. Please guide me how can I achieve this. Here I am popping up local notification when the GPS updates to a new location. Some code snippest is provided here:

我正在开发一个需要在 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 guide me how to do this?

请指导我如何做到这一点?

回答by Thyraz

Your info.plist contains this stuff?

你的 info.plist 包含这些东西?

An application can declare itself as a continuous background location application. An application that needs the regular location updates offered by the standard location services may declare itself as a continuous background application. It does this by including the UIBackgroundModes key in its Info.plist file and setting the value of this key to an array containing the location string. If an application with this key is running location services when it enters the background, it is not suspended by the system. Instead, it is allowed to continue running so that it may perform location-related tasks in the background.

应用程序可以将自己声明为连续的后台定位应用程序。需要由标准位置服务提供的定期位置更新的应用程序可以将自己声明为连续的后台应用程序。它通过在其 Info.plist 文件中包含 UIBackgroundModes 键并将此键的值设置为包含位置字符串的数组来实现此目的。如果具有此密钥的应用程序在进入后台时正在运行位置服务,则不会被系统挂起。相反,它被允许继续运行,以便它可以在后台执行与位置相关的任务。

http://developer.apple.com/library/ios/#documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html%23//apple_ref/doc/uid/TP40007072-CH5

http://developer.apple.com/library/ios/#documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html%23//apple_ref/doc/uid/TP40007072-CH5

回答by BadPirate

You don't need to do the beginBackgroundTask... (in fact you shouldn't), by signing up for location updates (see the post above this one), your application will automatically be awoken and notified of location changes. Background Tasks are for another purpose (extended downloading etc.), and you only have a limited time to do them (around 10 minutes), if you try to keep a background task open longer then that, your application will be terminated.

您不需要执行 beginBackgroundTask...(实际上您不应该),通过注册位置更新(请参阅上面的帖子),您的应用程序将自动被唤醒并通知位置更改。后台任务用于其他目的(扩展下载等),您只有有限的时间来执行它们(大约 10 分钟),如果您尝试让后台任务打开更长时间,您的应用程序将被终止。

Basically get rid of the beginBackgroundTask stuff, and add the UIBackgroundModes -> location key to your info.plist so that you are registered to have your app notified of location changes even while in the background.

基本上摆脱了 beginBackgroundTask 的东西,并将 UIBackgroundModes -> 位置键添加到您的 info.plist 以便您注册以让您的应用程序通知位置更改,即使在后台也是如此。