iOS为什么系统使用后台位置

时间:2016-07-06 11:11:10

标签: ios swift core-location location-services

我有一个应用程序,它在前台和后台使用位置更新。使用CoreLocation框架,我已经实现了应用程序,以便每隔5分钟将位置更新发送到服务器,并使用this代码作为参考。

这在前台工作正常,但当应用程序进入后台时,它会在30分钟到一小时后被操作系统杀死。我希望应用程序至少在8小时内获得更新,即使在后台也是如此。

此外,该应用程序每小时使用约10%的电池。这与应用程序在后台被杀是否相关?如果是这样,那么我该如何解决电池问题呢?否则,谁能告诉我这是什么问题?

以下是设备的崩溃日志:

Exception Type:  00000020
Exception Codes: 0x000000008badf00d
Exception Note:  SIMULATED (this is NOT a crash)
Highlighted by Thread:  2

Application Specific Information:
<BKNewProcess: 0x17e74840; com.app.app; pid: 560; hostpid: -1> has active assertions beyond permitted time: 
{(
<BKProcessAssertion: 0x17d78740> id: 560-C9E81E97-90D9-4F95-871E-3DC53372F302 name: Called by UIKit, from <redacted> process: <BKNewProcess: 0x17e74840; com.app.example; pid: 560; hostpid: -1> permittedBackgroundDuration: 180.000000 reason: finishTask owner pid:560 preventSuspend  preventIdleSleep  preventSuspendOnSleep ,
<BKProcessAssertion: 0x17e6a870> id: 560-BD7B29FC-DABC-42FF-AF17-B277BDB1C59D name: Called by UIKit, from <redacted> process: <BKNewProcess: 0x17e74840; com.app.example; pid: 560; hostpid: -1> permittedBackgroundDuration: 180.000000 reason: finishTask owner pid:560 preventSuspend  preventIdleSleep  preventSuspendOnSleep 
)}

对于后台任务,我使用以下功能:

func backgroundTask(){
    var application=UIApplication.sharedApplication()
    var background_task: UIBackgroundTaskIdentifier?
    background_task = application.beginBackgroundTaskWithExpirationHandler({() -> Void in
        application.endBackgroundTask(background_task!)
        background_task = UIBackgroundTaskInvalid
    })
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {() -> Void in
        //run the app without startUpdatingLocation. backgroundTimeRemaining decremented from 600.00
        self.locationManager.startUpdatingLocation()
        while (true) {
            //backgroundTimeRemaining time does not go down.
            print("Background time Remaining: \(UIApplication.sharedApplication().backgroundTimeRemaining)")
            NSThread.sleepForTimeInterval(1)

            break
            //wait for 1 sec
        }
        application.endBackgroundTask(background_task!)
        background_task = UIBackgroundTaskInvalid
    })

}

5 个答案:

答案 0 :(得分:3)

当您的应用进入后台状态时,切换到significant location updates,您的应用会不断收到位置更新。您可以在startMonitoringSignificantLocationChanges的{​​{1}}对象上调用CLLocationManger。而且我认为你也不需要建立后台任务。

检查Apple Documentation,它说明,

  

如果您启动此服务并且您的应用随后终止,则系统会在新事件到来时自动将应用重新启动到后台。在这种情况下,传递给应用程序的选项字典:willFinishLaunchingWithOptions:和application:didFinishLaunchingWithOptions:应用程序委托的方法包含密钥UIApplicationLaunchOptionsLocationKey,以指示您的应用程序是由于位置事件而启动的。重新启动后,您仍必须配置位置管理器对象并调用此方法以继续接收位置事件。重新启动位置服务时,会立即将当前事件传递给您的代理。此外,即使在启动位置服务之前,您的位置管理器对象的位置属性也会填充最新的位置对象

所以,它会解决你的问题,我认为它也会解决电池问题。

第二件事(对于电池消耗),当您想要在后台长时间更新位置时,不应将DesiredAccuracy设置为kCLLocationAccuracyBest。您可以将kCLLocationAccuracyThreeKilometers设置为DesiredAccuracy,并在后台输入时将setDistanceFilter设置为非常大的数字,如99999

您可以参考this so postthis so post

希望这会有所帮助:)

答案 1 :(得分:1)

你有没有任何崩溃日志。如果应用程序没有被一些隐藏的bug除外,你应该怀疑内存压力。我想这篇文章将引导你找到突然终止的原因

https://www.raywenderlich.com/23704/demystifying-ios-application-crash-logs

答案 2 :(得分:1)

@Lion表示在后台输入时使用重要位置更改。我使用SLC时遇到了同样的问题,所以你也会有这个问题。当应用程序进入后台时,由于内存警告,它被系统杀死。所以我做的是为CoreLocation创建一个单例,它将接收CoreLocation的所有委托调用。

为了在后台重新启动您的服务,以防它被杀:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
 if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey]) {

        //NSLog(@"Restarting SCL");
        LocationService *loc = [LocationService sharedInstance];
        [loc setManagedObjectContext:self.managedObjectContext];
}

LocationService是我的单身人士。

还在AppDelegate中实现此功能以处理内存警告通知:

-(void)applicationDidReceiveMemoryWarning:(UIApplication *)application
{
    //Sending notification to every controller to free some memory
    [[NSNotificationCenter defaultCenter] postNotificationName:@"freeMemory" object:nil userInfo:nil];

    SDImageCache *imageCache = [SDImageCache sharedImageCache];
    [imageCache clearMemory];
    [imageCache clearDisk];

    //NSLog(@"Received memory warning!");
}

例如清除图像缓存。 此外,我正在使用MapView确保取消您不能使用的任何内容,因为非常昂贵的视图(以及泄漏的错误)。

答案 3 :(得分:0)

另外注意,您需要注册才能接收后台位置更新。可能不太清楚的是,这与&#34;在背景中一直在做任何你想做的事情都是不一样的。&#34;这意味着在不同的时间,在系统的判断下,您将被发送位置数据,您必须尽快处理该位置数据然后返回。当系统选择时,您将再次被调用。可能正在运行其他位置服务。系统尝试通过合并所有不同的位置客户端来优化它。

后台任务,就像您尝试使用的那样,是一个完全不同的问题。他们要求&#34;多加一点时间&#34;在用户退出应用程序时完成某项工作。像清理数据库之类的东西。如果你让它们继续运转,你就会被杀死。看看你当前的代码,看起来它实际上并没有做任何事情,因为看起来它在一次调用后突然出现了循环。但是,任何调用NSThread.sleepForTimeInterval(1)的代码几乎都会在iOS中保证不正确。几乎没有理由打电话。但是,您不应该需要后台任务来管理位置更新。

答案 4 :(得分:0)

我之所以发布此答案,是因为大家都说这是操作系统的默认行为,我们无法更改它。...bla .... bla。

最近,我正在处理相同的要求。经过2-3周的努力,我做到了。对于其他用户,我为其创建了一个帮助器类。在运行位置跟踪之前,我的应用永远不会被操作系统杀死。

使用HSLocationManager在有效和无效状态下进行无限位置跟踪。

请参阅我在应用商店中可用的应用(如果运行位置跟踪,则应用将不会被操作系统杀死):Capchur

  

位置管理器,可让每个位置获取后台位置更新   n秒,并具有所需的定位精度。

     

优势:

     
      
  • 如果位置管理器当前处于运行状态,则操作系统将永远不会杀死我们的应用程序   正在运行。

  •   
  • 在需要时定期提供位置更新(范围介于2-   170秒(受允许的最大后台任务时间限制)

  •   
  • 可自定义的位置准确性和时间段。

  •   
  • 低内存消耗(Singleton类)

  •