这里还有一个关于在后台运行 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;
}];
所以现在,我最大的问题是:我还没有做/做错什么,不允许后台执行?
- 我的应用程序有一个 csv 日志文件(本地),它记录了哪些 GPS 坐标被发送到跟踪网络服务。在我的日志中,我还记录了“App to Background”和“App to Foreground”等事件,因此当我检索日志时,我会知道它是否在 3 分钟后终止。此外,我记录了
[[UIApplication sharedApplication] backgroundTimeRemaining]
剩余时间。 - 我有
CLLocationManager *locationManager;
。当我的应用程序进入后台时,我制作了[locationManager setDesiredAccuracy:kCLLocationAccuracyThreeKilometers];
然后[locationManager startUpdatingLocation];
只是为了让应用程序在后台运行。计时器在如上所述的间隔时更改[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
,然后将其更改回[locationManager setDesiredAccuracy:kCLLocationAccuracyThreeKilometers]
。所有这些都是当应用程序在后台时,[locationManager stopUpdatingLocation];
只有当应用程序在前台时。我真的需要让 locationManager 保持运行以便应用程序在后台保持事件状态吗? 奇怪的部分如下:我意识到当我通过以下方式将我的应用程序发送到后台时:(a.) 主页按钮 (b.) 电源按钮 (c.) 关闭 iPad 外壳,(a. ) 将始终让应用程序在后台运行,而 (b.) 和 (c.) 可能 允许应用程序运行超过 3 分钟??!?真的有区别吗?因为我知道委托(delegate)函数它是否运行超过 3 分钟似乎是不确定的。applicationWillResignActive
和applicationDidEnterBackground
仍然会被调用。- 我是否将
beginBackgroundTaskWithExpirationHandler
放在了正确的位置? - 我是否将
[locationManager setAllowsBackgroundLocationUpdates:YES];
放在了正确的位置(目前在 AppDelegaate 中)? - 使用 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/