iOS9 Objective-C 使用定时器在后台运行 GPS

标签 ios objective-c timer background gps

这里还有一个关于在后台运行 GPS 的问题。显然,在特定条件下我的应用程序可以在后台运行(似乎无限期地),有时它会在 3 分钟后终止。我的 iPad 当前运行的是 9.3.2。

TL;DR:进行了必要的代码和项目配置,但并不总是在后台运行超过 3 分钟。为什么?

我的帖子会很长。我尽量保持简洁。

我的应用程序需要每隔一段时间发送一次 GPS 位置:如果用户“已登录”则为 60 秒,如果用户“已注销”则为 900 秒(15 分钟)。我需要这些要求; 类(class)要求不是我决定的。此应用也未发布到应用商店。

我知道我需要在我的 plist 中添加这个:

<key>NSLocationAlwaysUsageDescription</key>
<string>Location information from this device is required for tracking purposes.</string>

在项目功能下,我选择了背景模式 -> 位置更新,并且也在 plist 中:

<key>UIBackgroundModes</key>
<array>
    <string>location</string>
</array>

在我的 AppDelegate 中,我还有这 2 个(位于 application:didFinishLaunchingWithOptions: 中):

if ([locationManager respondsToSelector:@selector(requestAlwaysAuthorization)])
{
    [locationManager requestAlwaysAuthorization];
    NSLog(@"===>locationManager responds to requestAlwaysAuthorization<===");
    }
    else
{
    NSLog(@"===>locationManager not responding to requestAlwaysAuthorization! :(<===");
}

if([locationManager respondsToSelector:@selector(setAllowsBackgroundLocationUpdates:)])
{
    [locationManager setAllowsBackgroundLocationUpdates:YES];
    NSLog(@"===>locationManager responds to setAllowsBackgroundLocationUpdates<===");
}
else
{
     NSLog(@"===>locationManager not responding to setAllowsBackgroundLocationUpdates! :(<===");
}

在我的 applicationDidEnterBackground 中,我有 beginBackgroundTaskWithExpirationHandler 函数,如下所示:

bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
    NSLog(@"ending background task. Background time remaining: %f", [[UIApplication sharedApplication] backgroundTimeRemaining]);
    //Do I need to uncomment the 2 lines below?
    //[[UIApplication sharedApplication] endBackgroundTask:bgTask];
    //bgTask = UIBackgroundTaskInvalid;
}];

所以现在,我最大的问题是:我还没有做/做错什么,不允许后台执行?

  1. 我的应用程序有一个 csv 日志文件(本地),它记录了哪些 GPS 坐标被发送到跟踪网络服务。在我的日志中,我还记录了“App to Background”和“App to Foreground”等事件,因此当我检索日志时,我会知道它是否在 3 分钟后终止。此外,我记录了 [[UIApplication sharedApplication] backgroundTimeRemaining] 剩余时间。
  2. 我有 CLLocationManager *locationManager;。当我的应用程序进入后台时,我制作了 [locationManager setDesiredAccuracy:kCLLocationAccuracyThreeKilometers]; 然后 [locationManager startUpdatingLocation]; 只是为了让应用程序在后台运行。计时器在如上所述的间隔时更改 [locationManager setDesiredAccuracy:kCLLocationAccuracyBest];,然后将其更改回 [locationManager setDesiredAccuracy:kCLLocationAccuracyThreeKilometers]。所有这些都是当应用程序在后台时,[locationManager stopUpdatingLocation]; 只有当应用程序在前台时。我真的需要让 locationManager 保持运行以便应用程序在后台保持事件状态吗?
  3. 奇怪的部分如下:我意识到当我通过以下方式将我的应用程序发送到后台时:(a.) 主页按钮 (b.) 电源按钮 (c.) 关闭 iPad 外壳,(a. ) 将始终让应用程序在后台运行,而 (b.) 和 (c.) 可能 允许应用程序运行超过 3 分钟??!?真的有区别吗?因为我知道委托(delegate)函数 applicationWillResignActiveapplicationDidEnterBackground 仍然会被调用。 它是否运行超过 3 分钟似乎是不确定的。
  4. 我是否将 beginBackgroundTaskWithExpirationHandler 放在了正确的位置?
  5. 我是否将 [locationManager setAllowsBackgroundLocationUpdates:YES]; 放在了正确的位置(目前在 AppDelegaate 中)?
  6. 使用 xcode 调试器运行应用程序将始终完美运行,但在没有(即实际使用条件)的情况下运行它可能无法让应用程序运行。随着调试器的运行,我 NSLog 剩余的后台时间。它可能会显示 179.348015 秒之类的内容,但 3 分钟后应用程序将继续运行。其他人是否遇到过这个问题?

非常感谢您的帮助。 o/

最佳答案

好吧,所以我在 1 年前问过这个问题,但没有收到任何回复...

当我第一次问这个问题时,我的意图是在应用程序获取坐标后关闭 GPS。所以在伪代码中,逻辑应该是这样的:

applicationStart()
{
    startTimer();
}

startTimer()
{
    timer repeats: TRUE;
    timer cycle: 60 seconds;
    function to call: getGPS();
}

getGPS()
{
    GPS start;
    retrieve coordinates;
    send coordinates to server;
    GPS stop;
}

这样做是为了节省电池电量,因为 GPS 是一项耗电功能。但是,这样做并不能保证 GPS 会一直在后台运行。最重要的是,正如我所提到的,运行这种逻辑的结果是不确定的;有时会运行,有时不会。

最后,我当前的代码是这样的(伪代码):

applicationStart()
{
    GPS start;
    GPS accuracy 3 kilometers;
    startTimer();
}

startTimer()
{
    timer repeats: TRUE;
    timer cycle: 60 seconds;
    function to call: getGPS();
}

getGPS()
{
    GPS accuracy best;
    retrieve coordinates;
    send coordinates to server;
    GPS accuracy 3 kilometers;
}

请注意,我实际上并没有关闭 GPS;代替关闭它,我让它不断运行,但在我不需要它时更改为 [locationManager setDesiredAccuracy:kCLLocationAccuracyThreeKilometers]

当然,我仍然愿意接受更好的解决方案。在问这个问题时,我正在运行 iOS9。我的上述解决方案现在适用于 iOS10,随着 iOS11 的临近,我不确定 Apple 将对与 GPS 相关的 API 带来哪些其他变化。

电池消耗?好吧,到目前为止还不错;我的用户没有提示。

关于iOS9 Objective-C 使用定时器在后台运行 GPS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38969705/

相关文章:

iPhone 应用程序 - 防止垃圾邮件

iphone - 使用 native Trigger.IO API 将 UIImage 传递给 JS

iphone - 我们在ios开发中必须遵循的编码标准有哪些

iOS:如何让定时器应用程序在后台播放自定义声音?

android - 如何暂停 CountDownTimer?

.net - 在 .NET 中创建的 OpenXML 电子表格无法在 iPad 中打开

ios - 在 native react 中动态需要 json 文件(来自数千个文件)

iphone - 执行 "if"条件 "x"毫秒并停止 "y"毫秒并重复条件?

ios - NSUserDefaults 机会 UISwitch 值

java - 使用 java swing Timer 处理文本并将其附加到文本区域