iOS 9后台使用Web服务更新和更新服务器上的位置

时间:2015-10-02 09:04:23

标签: ios iphone cllocationmanager background-process location-services

我开发了一个应用程序,它能够在应用程序处于后台和前台时更新服务器上的位置。我使用了Timer,它以1分钟的时间间隔不断更新位置,因为如果间隔超过1分钟,import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.joda.time.Interval; public class HelloWorld { public static void main(String[] args) { DateTime startWithTZ = new DateTime("2016-10-01T00:00:00", DateTimeZone.UTC); DateTime endWithTZ = new DateTime("2016-10-01T11:00:00", DateTimeZone.UTC); Interval intervalWithTZ = new Interval(startWithTZ, endWithTZ); DateTime startWithoutTZ = new DateTime("2016-10-01T00:00:00"); DateTime endWithoutTZ = new DateTime("2016-10-01T11:00:00"); Interval intervalWithoutTZ = new Interval(startWithoutTZ, endWithoutTZ); Interval utcInterval = new Interval(intervalWithoutTZ.getStart().withZoneRetainFields(DateTimeZone.UTC), intervalWithoutTZ.getEnd().withZoneRetainFields(DateTimeZone.UTC)); System.out.println(utcInterval); } } 会在后台暂停应用程序。

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

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

iOS

注意:在iOS 7和iOS 8中,一切都运行良好。

我已尝试过stackoverflow上提供的几种解决方案,但我无法找出可以解决问题的确切解决方案。

此外,我发现如果我没有锁定设备,那么位置更新和网络服务调用工作正常,但如果设备被锁定,则会停止更新位置并调用网络服务。

任何帮助都将受到高度赞赏。

提前谢谢。

更新

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

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;
}

注意:持续更新位置服务会大大耗尽iOS设备的电量。因此,只要您不使用更新的位置,就可以使用-(void)updateUsersLocation { // Your code goes here. }

3 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

我遇到了同样的问题。

新的 allowBackgroundLocationUpdates 无法保留在plist中,您必须将其放入代码中。

myLM = [[CLLocationManager alloc] init];
if([myLM respondsToSelector:@selector(allowsBackgroundLocationUpdates)]) {
   [myLM setAllowsBackgroundLocationUpdates: YES];
}

答案 2 :(得分:1)

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