如何在后台追踪用户位置?

20

我正在寻找一个开源的应用程序或库来在后台跟踪用户位置。现在我正在尝试使用 CLLocation 和后台任务来实现,但精度对我的情况来说不够。您能否解释一下,像 "moves"、"runkeeper"、"endmondo" 这样的应用程序是如何创建我的路线的?我应该使用加速计和/或指南针来创建 CLLocation 后台点之间的路线吗?

部分代码:

//location manager init
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.delegate = self;


#pragma mark - CLLocationManager Delegate

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {

    if ([self isInBackground]) {
        if (self.locationUpdatedInBackground) {
            bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler: ^{
                [[UIApplication sharedApplication] endBackgroundTask:bgTask];
            }];

            self.locationUpdatedInBackground(newLocation);
            [self endBackgroundTask];
        }
    } else {
        if (self.locationUpdatedInForeground) {
            self.locationUpdatedInForeground(newLocation);
        }
    }
}

更新: 刚刚测试了我的应用程序,使用了下一个属性。

self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.activityType = CLActivityTypeFitness;
self.locationManager.pausesLocationUpdatesAutomatically=NO;

在这种情况下,我在1.5小时的旅程中有大约10个已触发事件。


请至少发布设置CLLocationManager和启动位置管理器的代码。 - AlexWien
你在plist文件中设置了GPS后台模式入口吗? - AlexWien
@AlexWien 当然,我做了。 - Alexey Sidorov
我用我的应用程序进行了测试:它可以在后台模式下运行ios6,目标= ios5。 - AlexWien
@AlexWien 刚刚更新了主题并添加了一些测试。 - Alexey Sidorov
还是不行吗?请在第一行加入 NSLog("didUpdateLocation")。 - AlexWien
8个回答

7

使用

kCLLocationAccuracyBestForNavigation

请参考这里


6

您需要在"Info.plist"文件中添加键UIBackgroundModes (数组),其值为 "location" (应用程序注册位置更新)。

您可以在此处查看所有后台模式。


我已经完成了。在后台模式下,我在1.5小时的行程中大约有10个位置更新事件被触发。 - Alexey Sidorov

4
所以你的应用程序使用位置服务。请阅读定位感知编程指南
您需要对Info.plist进行一些更改:
- 如果您的应用程序依赖于位置服务以正常工作,请将location-services添加到UIRequiredDeviceCapabilities中 - 如果您的应用程序需要GPS硬件,请将gps添加到UIRequiredDeviceCapabilities中 - 如果您需要在背景中运行应用程序超过10分钟,请将location添加到UIBackgroundModes中。然后,您的位置管理器将传递超过10分钟限制的位置。 - 您还应该设置NSLocationUsageDescription(也可以本地化)
在后台获取位置事件
如果您的应用程序需要在前台或后台交付位置更新,请有多种选项可供选择。首选选项是使用重要位置更改服务,在适当的时间唤醒您的应用程序处理新事件。但是,如果您的应用程序需要使用标准位置服务,则可以声明您的应用程序需要后台位置服务。
仅当缺少这些服务会损害其操作能力时,应用程序才应请求后台位置服务。此外,请求后台位置服务的任何应用程序都应使用这些服务为用户提供实际的好处。例如,按路线导航应用程序将成为后台位置服务的一个可能候选者,因为它需要跟踪用户的位置并在到达下一个转弯时报告。

3
您的问题在于后台处理程序。删除它并在plist文件中启用GPS后台模式,然后您应该始终获得完整电量的GPS。
设置属性 pausesLocationUpdatesAutomatically=NO 这是iOS6中的新功能。
来自CLLocationManager
允许位置管理器暂停更新可以提高目标设备的电池寿命,而不会牺牲位置数据。当将此属性设置为YES时,位置管理器会在位置数据不太可能更改的时间暂停更新(并关闭适当的硬件)。例如,如果用户在使用导航应用程序时停下来吃饭,位置管理器可能会暂停更新一段时间。您可以通过为activityType属性分配值来帮助确定何时暂停位置更新。
此属性的默认值为YES。
要进行分析,请将这些方法添加到您的LocationManager委托中:
- (void)locationManagerDidPauseLocationUpdates:(CLLocationManager *)manager {
     NSLog(@"locMan: locationManagerDidPauseLocationUpdates");
}

- (void)locationManagerDidResumeLocationUpdates:(CLLocationManager *)manager {
    NSLog(@"locMan: locationManagerDidResumeLocationUpdates");
}

刚刚测试了我的应用程序,使用了以下属性: self.locationManager.distanceFilter = kCLDistanceFilterNone; self.locationManager.desiredAccuracy = kCLLocationAccuracyBest; self.locationManager.activityType = CLActivityTypeFitness; self.locationManager.pausesLocationUpdatesAutomatically=NO; 在这种情况下,在1.5小时的旅程中我有大约10个触发事件。 - Alexey Sidorov
我昨天测试了我的工作。尝试使用accuracyBestForNavigation来提高准确性。如果仍然不起作用,请尝试编译到目标iOS 5。 - AlexWien

2

您可以按照以下步骤在VC中设置监控位置信息:

在viewDidLoad方法中执行以下操作:

CLLocationManager locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;(Accuracy according to your need)
[locationManager startUpdatingLocation];

如果您使用的是iOS6+,则需要覆盖下面两个CLLocationManagerDelegate协议的可选委托方法:

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

并适用于iOS 2至6版本

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation

在这些方法中,您将获得更新的位置。您可以根据需要使用它。每次位置更新时,这些方法都会被调用。

感谢您的回复,但我正在寻找一种在后台模式下跟踪位置的解决方案,就像“moves”、“runkeeper”一样。我已尝试在后台模式下使用CLLocationkCLLocationAccuracyBest,但事件仅在每500米触发一次,这对我来说不够。 - Alexey Sidorov
@AlexeySidorov 这个修复程序几乎每秒钟触发一次,或者根据您的速度每秒钟触发一次。请再次阅读他的答案,您的应用程序在iOS5上工作吗? - AlexWien
@AlexWien 它在iOS6中可以工作。事件在后台模式下触发的频率不超过500米,这取决于蜂窝塔。我刚刚测试了一下。 - Alexey Sidorov
请查看 https://github.com/sidorov-panda/Record-my-position 它的工作方式相同,且触发的事件数量对我来说太少了。 - Alexey Sidorov
@AlexeySidorov,上周我将我的应用从iOS5移植到了iOS6,我会看看它在后台模式下的表现如何。 - AlexWien

1

你不是在要代码,而是在寻找一个开源的应用程序或库。

访问this网站可能会对你有所帮助。

希望能对你有所帮助,

同时还有一个tutorial


我正在寻找一个应用程序或方法的解释,就像“Moves”应用程序一样。 - Alexey Sidorov
这是一个非常好的应用程序,我也在使用它。您可以使用HTML5编写此代码,并使用Cordova框架完成您的应用程序,并将其添加到Android和Apple商店中。 - Marc Millet
我需要在后台跟踪步行,但该应用的准确度对我来说不够。 - Alexey Sidorov
RunKeeper应用程序与“moves”类似,您可以在github上获取源代码:https://github.com/brierwood/RunKeeper-iOS - Marc Millet
谢谢你的链接,它很有帮助,但是如果你发布通知,RunKeeper将自动为你创建一个正确的时间戳路径。 RunKeeperPathPoint *point = [[[RunKeeperPathPoint alloc] initWithLocation:newLocation ofType:kRKGPSPoint] autorelease]; [[NSNotificationCenter defaultCenter] postNotificationName:kRunKeeperNewPointNotification object:point]; - Alexey Sidorov
Alexey,我不是iOS专业编码人员,无法帮助你编写代码,我的技能是HTML5和CSS3,我的iOS知识处于中等水平。 - Marc Millet

0

这是我的解决方案,

声明实例变量:

CLLocationManager *locationManager;

请确保包含委托

<CLLocationManagerDelegate>

在viewDidLoad方法中:

locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone; // whenever we move, location is updated
locationManager.desiredAccuracy = kCLLocationAccuracyBest; // get best current locaton coords
locationManager.headingFilter = 1;
[locationManager startUpdatingLocation];
[locationManager startUpdatingHeading];

实现委托方法:

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
    int degrees = newLocation.coordinate.latitude;
    double decimal = fabs(newLocation.coordinate.latitude - degrees);
    int minutes = decimal * 60;
    double seconds = decimal * 3600 - minutes * 60;
    NSString *lat = [NSString stringWithFormat:@"%d° %d' %1.4f\"",
                     degrees, minutes, seconds];
    NSLog(@" Current Latitude : %@",lat);
    latitudeLocation.text = lat;
    degrees = newLocation.coordinate.longitude;
    decimal = fabs(newLocation.coordinate.longitude - degrees);
    minutes = decimal * 60;
    seconds = decimal * 3600 - minutes * 60;
    NSString *longt = [NSString stringWithFormat:@"%d° %d' %1.4f\"",
                       degrees, minutes, seconds];
    NSLog(@" Current Longitude : %@",longt);
    longitudeLocation.text = longt;
}

didUpdateToLocation方法已被弃用,并在iOS6中被didUpdateLocations:取代。 - Kheldar

-3

声明:我在Cintric工作。

我们还希望能够准确地在后台跟踪用户的位置(即使应用程序已被关闭)。我们花了很长时间解决这个问题,特别是关注电池耗尽的问题。

我们发布了一篇很棒的博客文章,介绍了我们如何解决这个问题。我们还提供了一个拖放式SDK解决方案。它不是开源的,但你可以免费集成它:

你可以下载.framework文件,将其拖入你的项目中,并用一行代码进行初始化:[CintricFind initWithApiKey:@"YOUR_API_KEY_HERE" andSecret:@"YOUR_SECRET_HERE"];

你可以免费获取API密钥。这里有解释所有内容的文档here


http://www.blog.cintric.com/?p=121没有链接到文章。你能修复这个链接吗? - Matt
链接应该被修复 :) - Joel Green
这个库不太好用。建议使用旧地图,因为位置更新不准确。 - Brave

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接