设备从休眠状态唤醒后,后台位置更新不会恢复

时间:2014-04-09 17:14:44

标签: ios core-location locationmanager

我遇到一个问题,即应用程序正在注册接收后台位置更新,直到设备休眠,然后在设备从休眠状态恢复后,位置更新不会恢复。

该应用程序非常简单,因为它可以测量位置更新对电池寿命的影响。

我使用单一视图应用程序模板创建了应用程序,并且:

  • 将以下发布的代码添加到应用代表处(其中没有其他代码) 代码)
  • 添加了位置更新后台模式
  • 添加了coreLocation.framework

当我启动应用程序然后将其移至后台时,didUpdateLocations:继续连续调用大约15-20分钟,并且每隔几秒就会执行getDataUsage()。

然后在大约15-20分钟后设备休眠(我在Organizer&#39的控制台上监控活动)。 但是,在唤醒设备后,应用程序永远不会收到任何didUpdateLocations:calls。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.locationManager = [[CLLocationManager alloc] init];
    self.locationManager.delegate = self;
    self.timeThatDataMonitoringStarted = [NSDate date];
    self.initialDataValuesSet = NO;

    CLLocationDegrees degreesFilter = 0.1;
    [self.locationManager setHeadingFilter: degreesFilter];
    self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    self.locationManager.distanceFilter = 10;
    [self.locationManager startUpdatingLocation];

    [self getDataUsage];

    return YES;
}

- (void) locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
    NSLog(@"******************** LOCATION didUpdateLocations ***************");
    static NSDate* previousDate;
    static int count = 0;
    if (previousDate)
    {
        NSTimeInterval timeInterval = [[NSDate date] timeIntervalSinceDate:previousDate];
        NSLog(@" LOCATION: count: %d time since last update: %f", ++count, timeInterval);
    }
    previousDate = [NSDate date];
}

- (void) getDataUsage
{
    NSTimeInterval elapsedTime = [[NSDate date] timeIntervalSinceDate: self.timeThatDataMonitoringStarted];
    NSLog(@"********* GETTING DATA USAGE. Elapsed time: %f **************",elapsedTime);
    NSArray *data = [self getDataCounters];

    NSNumber *wifiSentSinceBoot = (NSNumber*)data[0];
    NSNumber *wifiReceivedSinceBoot = (NSNumber*)data[1];
    NSNumber *wwanSentSinceBoot = (NSNumber*)data[2];
    NSNumber *wwanReceivedSinceBoot = (NSNumber*)data[3];

    int wifiSentSinceBootAsInt      = [wifiSentSinceBoot intValue];
    int wifiReceivedSinceBootAsInt  = [wifiReceivedSinceBoot intValue];
    int wWanSentSinceBootAsInt      = [wwanSentSinceBoot intValue];
    int wWanReceivedSinceBootAsInt  = [wwanReceivedSinceBoot intValue];

    static int initialWifiSent;
    static int initialWifiReceived;
    static int initialWWanSent;
    static int initialWWanReceived;
    if (!self.initialDataValuesSet)
    {
        self.initialDataValuesSet    = YES;
        initialWifiSent     = wifiSentSinceBootAsInt;
        initialWifiReceived = wifiReceivedSinceBootAsInt;
        initialWWanSent     = wWanSentSinceBootAsInt;
        initialWWanReceived = wWanReceivedSinceBootAsInt;
    }

    int wifiSentSinceLastRetrieval     = wifiSentSinceBootAsInt - initialWifiSent;
    int wifiReceivedSinceLastRetrieval = wifiReceivedSinceBootAsInt - initialWifiReceived;
    int wWanSentSinceLastRetrieval     = wWanSentSinceBootAsInt - initialWWanSent;
    int wWanReceivedSinceLastRetrieval  = wWanReceivedSinceBootAsInt - initialWWanReceived;

    uint dataUsed = wifiSentSinceLastRetrieval + wifiReceivedSinceLastRetrieval + wWanSentSinceLastRetrieval + wWanReceivedSinceLastRetrieval;
    NSLog(@"Total data: %d", dataUsed);
    [self performSelector:@selector(getDataUsage) withObject:nil afterDelay:3];
}


- (NSArray *) getDataCounters
{
    BOOL   success;
    struct ifaddrs *addrs;
    const struct ifaddrs *cursor;
    const struct if_data *networkStatisc;

    int WiFiSent = 0;
    int WiFiReceived = 0;
    int WWANSent = 0;
    int WWANReceived = 0;

    NSString *name=[[NSString alloc]init];

    success = getifaddrs(&addrs) == 0;
    if (success)
    {
        cursor = addrs;
        while (cursor != NULL)
        {
            name=[NSString stringWithFormat:@"%s",cursor->ifa_name];
            //   NSLog(@"ifa_name %s == %@\n", cursor->ifa_name,name);
            // names of interfaces: en0 is WiFi ,pdp_ip0 is WWAN

            if (cursor->ifa_addr->sa_family == AF_LINK)
            {
                if ([name hasPrefix:@"en"])
                {
                    networkStatisc = (const struct if_data *) cursor->ifa_data;
                    WiFiSent+=networkStatisc->ifi_obytes;
                    WiFiReceived+=networkStatisc->ifi_ibytes;
                    //  NSLog(@"WiFiSent %d ==%d",WiFiSent,networkStatisc->ifi_obytes);
                    //  NSLog(@"WiFiReceived %d ==%d",WiFiReceived,networkStatisc->ifi_ibytes);
                }

                if ([name hasPrefix:@"pdp_ip"])
                {
                    networkStatisc = (const struct if_data *) cursor->ifa_data;
                    WWANSent+=networkStatisc->ifi_obytes;
                    WWANReceived+=networkStatisc->ifi_ibytes;
                    //  NSLog(@"WWANSent %d ==%d",WWANSent,networkStatisc->ifi_obytes);
                    //  NSLog(@"WWANReceived %d ==%d",WWANReceived,networkStatisc->ifi_ibytes);
                }
            }

            cursor = cursor->ifa_next;
        }

        freeifaddrs(addrs);
    }

    return [NSArray arrayWithObjects:[NSNumber numberWithInt:WiFiSent], [NSNumber numberWithInt:WiFiReceived],[NSNumber numberWithInt:WWANSent],[NSNumber numberWithInt:WWANReceived], nil];
}

注意我使用术语"休眠"不是指应用程序状态而是指设备状态。如果您在Organizer控制台中观察设备活动,那么一段时间后设备将开始关闭。我打电话给这个冬眠,因为我不知道实际的iOS术语是什么,而且通过休眠,我也不是指自动锁定和屏幕睡眠。此后,这是一项单独的活动,我假设电话和GPS芯片等正在断电。  无论如何,在此之后"冬眠"已达到阶段,如果您在设备上恢复活动,则表示我没有获得didUpdateLocations。

1 个答案:

答案 0 :(得分:-1)

您需要从App委托方法移动getDataUsage方法调用:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

到CLLocationManager委托:

- (void) locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations

因为每次发生位置更新(调用上面的委托),就会调用你的getDataUsage。

尝试使用伪" For循环"使用performSelector是糟糕的设计,当应用程序处于后台模式时会导致不可预测的结果。所以你需要删除该行:

[self performSelector:@selector(getDataUsage) withObject:nil afterDelay:3];

如果您打算让应用在后台运行,我还会确保该应用已注册为后台模式。

我还会在这里回答一些细节: iOS7 Core Location not updating