社区首页 >问答首页 >在应用程序处于后台时启动CLLocationManager位置更新

在应用程序处于后台时启动CLLocationManager位置更新
EN

Stack Overflow用户
提问于 2016-05-05 00:19:20
回答 1查看 1.7K关注 0票数 12

我正在构建一个应用程序,它使用CoreLocation有两个目的:

  1. 第一,监测信标区域。大多数情况下,我们使用的是作为信标的特定硬件设备,我们使用CoreLocation跟踪该信标连接的状态。
  2. 其次,当应用程序检测到从信标设备断开连接时,我们希望启动一个GPS进程来定位断开连接的位置。

在大多数情况下,当应用程序处于后台时,信号设备的断开回调就会发生。因此,应用程序必须在后台调用-startUpdatingLocation来启动GPS跟踪。

这就是问题所在。当应用程序处于后台时,iOS似乎不启用位置后台更新,如果-startUpdatingLocation调用发生在后台。

显然,我已经正确配置了背景模式NSLocationAlwaysUsageDescription,将属性_locationManager.allowsBackgroundLocationUpdates设置为YES

令人惊奇的是:如果我在前台时调用-startUpdatingLocation,然后切换到后台,则在后台时正确地发送位置更新。但是,在后台调用-startUpdatingLocation时,应用程序会收到2或3个位置更新,然后永远暂停。直到我手动将应用程序带回前台,当位置更新恢复,然后继续工作,即使我再次切换到后台应用程序。

有人知道或明白我该怎么做才能解决这个问题吗?还是iOS的一个主要制约因素?由于我的应用程序的要求,我真的需要开始定位更新时,应用程序在后台(在回调的信标,确实退出区域)。

顺便说一句,如果你想复制这个问题是很容易的。只需在Xcode中创建一个空白项目,并将此代码添加到默认视图控制器中即可。记住要启用背景模式,在info.plist键"NSLocationAlwaysUsageDescription“中添加一个描述。

代码语言:javascript
代码运行次数:0
复制
- (void)viewDidLoad 
{
    [super viewDidLoad];

    _locationManager = [[CLLocationManager alloc] init];

    if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_8_3)
        _locationManager.allowsBackgroundLocationUpdates = YES;

    _locationManager.delegate = self;
    _locationManager.activityType = CLActivityTypeOther;
    _locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    _locationManager.distanceFilter = kCLDistanceFilterNone;

    [_locationManager requestAlwaysAuthorization];

    // Creating a background task to delay the start of the startUpdatingLocation
    __block UIBackgroundTaskIdentifier taskIdentifier = UIBackgroundTaskInvalid;
    taskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
        [[UIApplication sharedApplication] endBackgroundTask:taskIdentifier];
    }];

    // Delaying the call to startUpdatingLocation 10 seconds, enough time to dismiss the application
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [_locationManager startUpdatingLocation];
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [[UIApplication sharedApplication] endBackgroundTask:taskIdentifier];
        });
    });
}

然后,通过执行一些CLLocationManager来跟踪NSLogs委托,看看会发生什么。

谢谢,

EN

回答 1

Stack Overflow用户

发布于 2016-08-17 09:48:30

自从你贴出这个问题以来已经三个月了。你自己已经想出来了吗?

我试用了你的密码。我将一些NSLogs放在AppDelegate委托函数和viewDidLoad中。另外,在AppDelegate类中,我注销了留下的后台时间。

如果在进入后台之前调用了startUpdatingLocation

代码语言:javascript
代码运行次数:0
复制
2016-08-18 01:22:52.355 test background GPS from StackOF[2267:745042] viewDidLoad
2016-08-18 01:22:52.376 test background GPS from StackOF[2267:745042] _locationManager.allowsBackgroundLocationUpdates = YES;
2016-08-18 01:22:52.382 test background GPS from StackOF[2267:745042] _locationManager requestAlwaysAuthorization
2016-08-18 01:22:52.410 test background GPS from StackOF[2267:745042] applicationDidBecomeActive
2016-08-18 01:22:52.469 test background GPS from StackOF[2267:745042] viewDidAppear
2016-08-18 01:23:03.361 test background GPS from StackOF[2267:745042] [_locationManager startUpdatingLocation];
2016-08-18 01:23:03.362 test background GPS from StackOF[2267:745042] start updating location, _locationManager.allowsBackgroundLocationUpdates == YES
2016-08-18 01:23:03.382 test background GPS from StackOF[2267:745042] Lat/Long: <redacted GPS coordinates>, horizontal accuracy: 65.000000
2016-08-18 01:23:03.630 test background GPS from StackOF[2267:745042] Lat/Long: <redacted GPS coordinates>, horizontal accuracy: 1743.000000
2016-08-18 01:23:03.709 test background GPS from StackOF[2267:745042] Lat/Long: <redacted GPS coordinates>, horizontal accuracy: 1743.000000
2016-08-18 01:23:03.716 test background GPS from StackOF[2267:745042] Lat/Long: <redacted GPS coordinates>, horizontal accuracy: 1743.000000
2016-08-18 01:23:03.720 test background GPS from StackOF[2267:745042] Lat/Long: <redacted GPS coordinates>, horizontal accuracy: 1743.000000
2016-08-18 01:23:03.814 test background GPS from StackOF[2267:745042] Lat/Long: <redacted GPS coordinates>, horizontal accuracy: 65.000000
2016-08-18 01:23:05.004 test background GPS from StackOF[2267:745042] inner block [[UIApplication sharedApplication] endBackgroundTask:taskIdentifier];
2016-08-18 01:23:05.005 test background GPS from StackOF[2267:745042] inner block start updating location, _locationManager.allowsBackgroundLocationUpdates == YES
2016-08-18 01:23:08.287 test background GPS from StackOF[2267:745042] applicationDidEnterBackground. Background time left: 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000
2016-08-18 01:23:10.319 test background GPS from StackOF[2267:745042] Lat/Long: <redacted GPS coordinates>, horizontal accuracy: 65.000000
2016-08-18 01:23:19.321 test background GPS from StackOF[2267:745042] Lat/Long: <redacted GPS coordinates>, horizontal accuracy: 65.000000
/****
Keep on polling...
****/

如果在进入后台后调用startUpdatingLocation

代码语言:javascript
代码运行次数:0
复制
2016-08-18 01:34:29.023 test background GPS from StackOF[2285:747132] viewDidLoad
2016-08-18 01:34:29.030 test background GPS from StackOF[2285:747132] _locationManager.allowsBackgroundLocationUpdates = YES;
2016-08-18 01:34:29.033 test background GPS from StackOF[2285:747132] _locationManager requestAlwaysAuthorization
2016-08-18 01:34:29.047 test background GPS from StackOF[2285:747132] applicationDidBecomeActive
2016-08-18 01:34:29.104 test background GPS from StackOF[2285:747132] viewDidAppear
2016-08-18 01:34:31.612 test background GPS from StackOF[2285:747132] applicationDidEnterBackground. Background time left: 179.964144
2016-08-18 01:34:40.004 test background GPS from StackOF[2285:747132] [_locationManager startUpdatingLocation];
2016-08-18 01:34:40.006 test background GPS from StackOF[2285:747132] start updating location, _locationManager.allowsBackgroundLocationUpdates == YES
2016-08-18 01:34:40.290 test background GPS from StackOF[2285:747132] Lat/Long: <redacted GPS coordinates>, horizontal accuracy: 10.000000
2016-08-18 01:34:40.332 test background GPS from StackOF[2285:747132] Lat/Long: <redacted GPS coordinates>, horizontal accuracy: 355.117789
2016-08-18 01:34:40.336 test background GPS from StackOF[2285:747132] Lat/Long: <redacted GPS coordinates>, horizontal accuracy: 355.118536
2016-08-18 01:34:40.493 test background GPS from StackOF[2285:747132] Lat/Long: <redacted GPS coordinates>, horizontal accuracy: 355.141209
2016-08-18 01:34:40.496 test background GPS from StackOF[2285:747132] Lat/Long: <redacted GPS coordinates>, horizontal accuracy: 355.147748
2016-08-18 01:34:40.505 test background GPS from StackOF[2285:747132] Lat/Long: <redacted GPS coordinates>, horizontal accuracy: 355.148158
2016-08-18 01:34:40.507 test background GPS from StackOF[2285:747132] Lat/Long: <redacted GPS coordinates>, horizontal accuracy: 65.000000
2016-08-18 01:34:41.640 test background GPS from StackOF[2285:747132] inner block [[UIApplication sharedApplication] endBackgroundTask:taskIdentifier];
2016-08-18 01:34:41.642 test background GPS from StackOF[2285:747132] inner block start updating location, _locationManager.allowsBackgroundLocationUpdates == YES
/****
stops polling...
****/

注意剩下的背景时间。如果应用程序在CLLocationManager开始更新位置之前进入后台,则剩下的背景时间为3分钟。我不太确定自己,因为我也有我自己的全球定位系统的背景运行问题,但从这个简短的测试,似乎CLLocationManager必须被调用之前,应用程序进入后台。

下面是我把NSLogs放在这里的地方:

代码语言:javascript
代码运行次数:0
复制
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    NSLog(@"viewDidLoad");

    _locationManager = [[CLLocationManager alloc] init];

    if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_8_3)
    {
        _locationManager.allowsBackgroundLocationUpdates = YES;
        NSLog(@"_locationManager.allowsBackgroundLocationUpdates = YES;");
    }



    _locationManager.delegate = self;
    _locationManager.activityType = CLActivityTypeOther;
    _locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
    _locationManager.distanceFilter = kCLDistanceFilterNone;

    [_locationManager requestAlwaysAuthorization];
    NSLog(@"_locationManager requestAlwaysAuthorization");

    // Creating a background task to delay the start of the startUpdatingLocation
    __block UIBackgroundTaskIdentifier taskIdentifier = UIBackgroundTaskInvalid;
    taskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
        [[UIApplication sharedApplication] endBackgroundTask:taskIdentifier];
        NSLog(@"[[UIApplication sharedApplication] endBackgroundTask:taskIdentifier];");
    }];

    // Delaying the call to startUpdatingLocation 10 seconds, enough time to dismiss the application
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [_locationManager startUpdatingLocation];
        NSLog(@"[_locationManager startUpdatingLocation];");
        if(_locationManager.allowsBackgroundLocationUpdates == YES)
        {
            NSLog(@"start updating location, _locationManager.allowsBackgroundLocationUpdates == YES");
        }
        else
        {
            NSLog(@"start updating location, _locationManager.allowsBackgroundLocationUpdates == NO");
        }
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [[UIApplication sharedApplication] endBackgroundTask:taskIdentifier];
            NSLog(@"inner block [[UIApplication sharedApplication] endBackgroundTask:taskIdentifier];");
            if(_locationManager.allowsBackgroundLocationUpdates == YES)
            {
                NSLog(@"inner block start updating location, _locationManager.allowsBackgroundLocationUpdates == YES");
            }
            else
            {
                NSLog(@"inner block start updating location, _locationManager.allowsBackgroundLocationUpdates == NO");
            }

        });
    });

}

CLLocationManager委托函数:

代码语言:javascript
代码运行次数:0
复制
-(void)locationManager:(CLLocationManager *) manager didUpdateLocations:(nonnull NSArray<CLLocation *> *)locations
{
    CLLocation *location = [locations firstObject];
    NSLog(@"Lat/Long: %f %f, horizontal accuracy: %f",
          location.coordinate.latitude,
          location.coordinate.longitude,
          location.horizontalAccuracy);
}

AppDelegate:

代码语言:javascript
代码运行次数:0
复制
- (void)applicationDidEnterBackground:(UIApplication *)application {

    NSLog(@"applicationDidEnterBackground. Background time left: %f", [[UIApplication sharedApplication] backgroundTimeRemaining]);

}

TL;博士:尝试在viewDidLoad或AppDelegate application:didFinishLaunchingWithOptions:中调用startUpdatingLocation

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37045746

复制
相关文章
[译] 更可靠的 React 组件:组合及可重用性
原文摘自:https://dmitripavlutin.com/7-architectural-attributes-of-a-reliable-react-component/
江米小枣
2020/06/15
2.9K2
怎样开发可重用组件并发布到NPM [每日前端夜话0x24]
摘要:本文着眼于使用具有内置功能和样式的组件来扩充HTML。 我们还将学习如何通过 NPM 使这些自定义元素在项目中得到重用。
疯狂的技术宅
2019/03/27
1.1K0
怎样开发可重用组件并发布到NPM [每日前端夜话0x24]
如何使用SASS编写可重用的CSS
Sass 是一个CSS预处理程序,至今使用广泛,它之所以流行,是因为它修复了几个CSS缺陷:
前端小智@大迁世界
2022/06/15
7.7K0
如何使用SASS编写可重用的CSS
Logstash: 如何创建可维护和可重用的 Logstash 管道
Logstash 是一种开源数据处理管道,它从一个或多个输入中提取事件,对其进行转换,然后将每个事件发送至一个或多个输出。 一些 Logstash 实现可能具有多行代码,并且可能处理来自多个输入源的事件。 为了使此类实现更具可维护性,我将展示如何通过从模块化组件创建管道来提高代码的可重用性。
腾讯云大数据
2020/07/28
1.3K0
Logstash: 如何创建可维护和可重用的 Logstash 管道
在Vue中创建可重用的 Transition
Vue.js中的transition确实很棒。 毫无疑问,它们可以非常轻松地让应用程序栩栩如生,但是通常必须在每个项目中从头开始编写它们,甚至还需要引入animate.css之类的CSS库来使它们功能更强大。
前端小智@大迁世界
2020/06/04
9.8K0
在Vue中创建可重用的 Transition
开发容器:可重用的开发环境
作者 | Avdi Grimm 译者 | 明知山 策划 | 丁晓昀 拿着 Chromebook 在洗车房做开发 那天,我把车开到了洗车场。这是一个高级洗车场,你把车交给工作人员,然后等着他们把车里里外外清洗干净。 我要做的就是打发时间了。我还有一些代码要写,但当时我只有一台装在包里的小 Chromebook 和 WiFi 连接。 于是,我在 GitHub Codespaces 中打开了这个项目,然后在上次停下的地方继续,在云端运行我的开发环境。 不只是编辑器,而是整个为我的项目定制的虚拟机。
深度学习与Python
2023/04/01
1.2K0
开发容器:可重用的开发环境
代码质量--可重用代码
可重用的代码可以减少重复劳动。一个软件中,会有很多类似的业务场景。将这些场景抽象成可重用的代码。开发新功能时,重用代码可减少重复劳动。
FunTester
2023/08/04
1690
代码质量--可重用代码
可重用性的6个级别
这是有关级别的基本概述。我即将举行的课程“ 可重用组件 ”探讨了每个组件以及如何充分利用它们。
公众号---人生代码
2020/08/11
1.1K0
Vue3 Composition API中的提取和重用逻辑
Vue3 Composition API可以在大型项目中更好地组织代码。然儿,随着使用几种不同的选项属性切换到单一的 setup 方法,许多开发人员面临的问题是… …。
张张
2020/04/26
1.8K0
Vue3 Composition API中的提取和重用逻辑
ES中的api调用测试
SearchRequest可用于与搜索文档、聚合、建议有关的任何操作,还提供请求突出显示结果文档的方法。 
一个风轻云淡
2023/10/15
2240
调用谷歌翻译接口_api如何调用
在平时使用谷歌翻译的过程中,经常会遇到需要批量翻译大量文本的情景,这种时候需要调用谷歌翻译的API
全栈程序员站长
2022/11/03
4.7K0
如何实现可伸缩的 etcd API?
使用etcd grpc-proxy start的命令开启 etcd 的 gRPC proxy 模式,包含上表中的静态成员:
aoho求索
2021/06/16
1.4K0
代码质量第 2 层 - 可重用的代码
可重用的代码可以减少重复劳动。一个软件中,会有很多类似的业务场景。将这些场景抽象成可重用的代码。开发新功能时,重用代码可减少重复劳动。
前端GoGoGo
2021/12/14
9330
代码质量第 2 层 - 可重用的代码
可重用的代码可以减少重复劳动。一个软件中,会有很多类似的业务场景。将这些场景抽象成可重用的代码。开发新功能时,重用代码可减少重复劳动。
社区小番茄
2022/01/17
3.7K7
代码质量第 2 层 - 可重用的代码
96-可重用的TCP服务器
在95-socket基础:TCP服务器流程中,TCP服务器只能一个客户端连接,客户端也只能发送一条消息。本例允许客户端发送多条消息,输入end结束。客户端退出后,服务器程序不再退出,可以为下一个客户端提供服务:
凯茜的老爸
2018/09/11
1.1K0
ArkTS-@Styles定义组件重用样式
@Styles可以定义在组件内或全局,在全局定义时需在方法名前面添加function关键字,组件内定义时则不需要添加function关键字。
酒楼
2023/06/23
4670
在小程序中调用API在小程序中自定义弹窗组件
表明它是一个组件,我们称之为“子组件” 3. 注意:在组件wxss中不应使用ID选择器、属性选择器和标签名选择器。(只使用class)
九旬
2020/10/23
3K0
Vuejs中父组件主动调用子组件的方法
我们都知道,vue是单向流,但是有时候我们需要在父组件中主动通知子组件一些信息,使其做出一些响应变化,那么如何在父组件中去主动调用子组件的方法呢?Vue当然给我们提供了方法,如下:
飞奔去旅行
2019/06/13
5K0
WordPress可重用自定义css样式
因为别人的友情链接模板样式都是针对性的对于他们的主题使用的,自己搜了一下插件商店并没有现成的插件,只有自己写一个友情连接的页面样式,但是当前整站使用的是一个整体主题,不知道能不能修改,就慢慢从主题编辑器里面找。
Diuut
2022/11/22
6630
WordPress可重用自定义css样式
代码质量第2层-可重用的代码!
导语 | 腾讯云加社区精品内容栏目《云荐大咖》,特邀行业佼者,聚焦前沿技术的落地与理论实践,持续为您解读云时代热点技术,探秘行业发展新机。 可重用的代码指:在相似业务场景下,用的是同一份代码。 可重用的代码可以减少重复劳动。一个软件中,会有很多类似的业务场景。将这些场景抽象成可重用的代码。开发新功能时,重用代码可减少重复劳动。 可重用的代码可以减少因需求变动,导致多次改动和漏改的情况。试想,要修改全站提交按钮的颜色,如果全站有100个包含提交按钮的页面,每个页面的按钮的样式都没复用,这改动量和漏改的风险都
腾讯云开发者
2022/01/20
8340

相似问题

无法使用angular translate在angular中翻译

11

在Angular拦截器中使用Angular服务

110

在Angular应用程序中使用angular元素

11

如何使用@ Angular /upgrade在Angular 1应用中使用angular 2组件

112

如何使用angular-qrcode Angular?

10
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档