1

我开发了一个应用程序,它能够在应用程序处于后台和前台时更新服务器上的位置。我使用了 Timer,它以 1 分钟的时间间隔连续更新位置,因为如果间隔超过 1 分钟,则会iOS在后台暂停应用程序。

问题在于 iOS 9,当应用程序在后台时,有时它会停止位置更新,并在一段时间后再次启动。

这些是我从设备日志中找到的崩溃日志。

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

    Application Specific Information:
    <BKNewProcess: 0x15646220; com.com.com; pid: 1168; hostpid: -1> has active assertions beyond permitted time: 
    {(
        <BKProcessAssertion: 0x15537b80> id: 1168-1B744B09-0EB7-4B01-A6FE-F167669E4439 name: Called by UIKit, from <redacted> process: <BKNewProcess: 0x15646220; com.com.com; pid: 1168; hostpid: -1> permittedBackgroundDuration: 180.000000 reason: finishTask owner pid:1168 preventSuspend  preventIdleSleep  preventSuspendOnSleep ,
        <BKProcessAssertion: 0x15643480> id: 1168-59515322-D982-46F8-94A5-0DD259406664 name: Called by UIKit, from <redacted> process: <BKNewProcess: 0x15646220; com.com.com; pid: 1168; hostpid: -1> permittedBackgroundDuration: 180.000000 reason: finishTask owner pid:1168 preventSuspend  preventIdleSleep  preventSuspendOnSleep 
    )}
    Elapsed total CPU time (seconds): 6.880 (user 6.880, system 0.000), 9% CPU 
    Elapsed application CPU time (seconds): 0.081, 0% CPU

注意:在 iOS 7 和 iOS 8 中一切正常。

我已经尝试了 stackoverflow 上可用的几个解决方案,但我无法找出可以解决问题的确切解决方案。

我还发现,如果我不锁定设备,则位置更新和 Web 服务调用工作正常,但如果设备被锁定,它会停止更新位置并调用 Web 服务。

任何帮助将不胜感激。

先感谢您。

更新

AppDelegate.h

@property (nonatomic, retain) CLLocation *currentLocation;
@property (nonatomic, strong) NSTimer* locationUpdateTimer;
-(void)updateUsersLocation;
-(void)distroyTimer;

AppDelegate.m

-(void)callLocationManager
{
    @autoreleasepool
    {
        UIAlertView * alert;
        //We have to make sure that the Background App Refresh is enable for the Location updates to work in the background.
        if([[UIApplication sharedApplication] backgroundRefreshStatus] == UIBackgroundRefreshStatusDenied)
        {
            alert = [[UIAlertView alloc]initWithTitle:ALERTTITLE
                                              message:@"The app doesn't work without the Background App Refresh enabled. To turn it on, go to Settings > General > Background App Refresh"
                                             delegate:nil
                                    cancelButtonTitle:@"Ok"
                                    otherButtonTitles:nil, nil];
            [alert show];
            return;
        }
        else if([[UIApplication sharedApplication] backgroundRefreshStatus] == UIBackgroundRefreshStatusRestricted)
        {
            alert = [[UIAlertView alloc]initWithTitle:ALERTTITLE
                                              message:@"The functions of this app are limited because the Background App Refresh is disable."
                                             delegate:nil
                                    cancelButtonTitle:@"Ok"
                                    otherButtonTitles:nil, nil];
            [alert show];
            return;
        }
        else if(![CLLocationManager locationServicesEnabled])
        {
            UIAlertView *alert = [[UIAlertView alloc]
                                  initWithTitle:@""
                                  message:@"Please enable GPS service for HiHo Mobile From settings"
                                  delegate:nil
                                  cancelButtonTitle:@"OK"
                                  otherButtonTitles:nil];
            [alert show];
            return;
        }
        else
        {
            if (!self.locationManager)
            {
                self.locationManager = [[CLLocationManager alloc] init];
            }
            self.locationManager.delegate = self;
            // self.locationManager.distanceFilter = kCLDistanceFilterNone;
            self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
            self.locationManager.distanceFilter = 10.0f;
            self.locationManager.activityType = CLActivityTypeAutomotiveNavigation;

            if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
            {
                [self.locationManager requestAlwaysAuthorization];
            }

            if ([self.locationManager respondsToSelector:@selector(allowsBackgroundLocationUpdates)])
            {
                self.locationManager.allowsBackgroundLocationUpdates  = YES;
            }
            if ([self.locationManager respondsToSelector:@selector(pausesLocationUpdatesAutomatically)])
            {
                self.locationManager.pausesLocationUpdatesAutomatically= NO;
            }
            if([self.locationManager respondsToSelector:@selector(allowsBackgroundLocationUpdates)])
            {
                [self.locationManager setAllowsBackgroundLocationUpdates:YES];
            }
            [self.locationManager stopMonitoringSignificantLocationChanges];
            [self.locationManager startUpdatingLocation];

            if ([USERDEFAULTS boolForKey:@"someFlag"]==YES)
            {
                [self distroyTimer];
                self.locationUpdateTimer =
                [NSTimer scheduledTimerWithTimeInterval:180
                                                 target:self
                                               selector:@selector(updateUsersLocation)
                                               userInfo:nil
                                                repeats:YES];
                [[NSRunLoop mainRunLoop]addTimer:self.locationUpdateTimer forMode:NSRunLoopCommonModes];
            }
            else
            {
                [self.locationManager stopUpdatingLocation];
                [self.locationManager startMonitoringSignificantLocationChanges];
            }
        }
    }
}

-(void)distroyTimer
{
    if ([self.locationUpdateTimer isValid])
    {
        [self.locationUpdateTimer invalidate];
        self.locationUpdateTimer = nil;
    }
}

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
    NSLog(@"latitude: %f, longitude: %f",newLocation.coordinate.latitude, newLocation.coordinate.longitude);
    self.currentLocation = newLocation;
}

// 编写代码以更新服务器上的位置

-(void)updateUsersLocation
{
    // Your code goes here.
}

注意:位置服务的持续更新将极大地消耗您的 iOS 设备的电池。因此,一旦您没有使用更新的位置,您就可以使用significant locations.

4

3 回答 3

1

我保留了一个用于启动和停止位置管理器的计时器,因为我向苹果开发人员发布了同样的问题,他们建议我为应用程序保留一个位置管理器,并删除可能在应用程序在后台工作时在线程期间受到影响的计时器,所以最后我删除了计时器逻辑,现在位置管理器不断更新位置,直到用户退出。这可能会耗尽电池电量,但这是我找到的唯一解决方案,并且适用于我们的应用程序。

于 2015-11-26T11:15:43.953 回答
1

您应该使用位置更新后台模式在后台获取位置更新,然后当调用 didupdalocation 时,您的应用将从后台唤醒。请参阅文档以获得更好的理解。

于 2015-10-02T09:17:40.787 回答
1

我遇到过同样的问题。

新的allowBackgroundLocationUpdates不能停留在plist,必须放到代码中。

myLM = [[CLLocationManager alloc] init];
if([myLM respondsToSelector:@selector(allowsBackgroundLocationUpdates)]) {
   [myLM setAllowsBackgroundLocationUpdates: YES];
}
于 2015-10-02T14:44:24.553 回答