我正在为 iOS 7 创建基于导航的应用,因为我正在使用用户位置数据,使用CoreLocation框架,
应用程序要求是在特定时间开始获取用户在后台的位置,为此我已使用didReceiveRemoteNotification fetchCompletionHandler:
方法实现了静默推送,
我已成功实施使用无声推送&它调用startUpdatingLocation
,我能够在委托方法中获取位置数据:
使用此有效负载:
{"aps" : {"content-available" : 1},"SilentPush" : "4"}
我启用了location
&背景模式remote notification
:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler
{
__block UIBackgroundTaskIdentifier bgTask =0;
UIApplication *app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[self.locationManager startUpdatingLocation];
}];
didUpdateLocations
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
lastLoc=[locations lastObject];
[logFile addLocObject:[NSString stringWithFormat:@"Loc: %@",lastLoc]];
}
但问题是:
在位置类的几秒钟的委托方法是停止,如果设备在移动它不会发送任何数据,当我说话的应用前景,将所谓的“didFinishLaunhing”的方法,所以我想操作系统将杀死应用程序甚至位置是更新
在设备Diagnostics & usage
中,我收到了崩溃报告:
Application Specific Information:
MockUpApp2[390] has active assertions beyond permitted time:
{(
<BKProcessAssertion: 0x145ac790> identifier: Called by MockUpApp2, from -[AppDelegate application:didReceiveRemoteNotification:fetchCompletionHandler:] process: MockUpApp2[390] permittedBackgroundDuration: 40.000000 reason: finishTaskAfterBackgroundContentFetching owner pid:390 preventSuspend preventIdleSleep preventSuspendOnSleep
)}
昨天我已经问this question现在我可以通过推送通知在后台启动定位管理器,
所以请任何人都可以解决这个问题。
谢谢。
注意:如果我在调试模式下运行应用程序,则表示我通过XCode&amp; amp;不停止或不断开连接,应用程序将运行..在这种情况下,应用程序不会停止操作系统。
编辑1
根据@Stephen Darlington回答我是否删除所有backgroundfatcher 等,
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler
{
[self.locationManager startUpdatingLocation];
}
现在app甚至不会调用didUpdateLocations
,:(
我应该用这种方法写什么?
Edit 2
根据Apple Doc说:
If your app is suspended or not running, the system wakes up or launches your app and puts it into the background running state before calling the method.
那么,应用程序应该在后台运行很长时间,因为我启用了位置背景模式,?
答案 0 :(得分:3)
我不认为iOS上的后台处理工作方式与您期望的方式相同。它不像在Mac或Windows上,你可以在后台无限期运行(即使在iOS 7中有变化)。
所以,直接回答你的问题:你开始了一个可以继续在后台运行的任务。有两个“但是。”
beginBackgroundTaskWithExpirationHandler
之后的行。当你完成后,你会说endBackgroundTask:
beginBackgroundTaskWithExpirationHandler:
内容。即使应用程序在后台,总结一下:删除beginBackgroundTaskWithExpirationHandler:
语句。您只需要添加startUpdatingLocation:
。
答案 1 :(得分:2)
前段时间我在CLLocation上做了很多工作,我有一些意见和建议,但可能不是完整的解决方案。
我看到你正在对beginBackgroundTaskWithExpirationHandler
块中的无声通知做出反应。我不认为这是正确的。我相信你应该在CLLocationDelegate方法上使用那个backgroundTask模式。
更重要的是,Apple很有可能会拒绝您使用位置标记进行后台处理。借鉴我的经验。我花了很多时间来合理使用位置服务来提高我自己的流程的准确性。我甚至启用了许多防止过度使用电池的保护措施,他们在没有讨论的情况下拒绝了它。我做到了这样它只在设备插入充电器时才使用后台服务。我上诉并为负责任的使用做了一个很好的案例,但没有用。
您应该查看这些条款,并确保您的用例正确地包含在内,或者它不会浮动。
我仍然说你可以在没有后台服务的情况下得到你想要的东西。使用重要的位置更改和区域监控,您的应用除了保存最新的已知位置和响应通知外,不需要任何其他内容。
我会想到一个像这样的计划:
在我看来,你是以错误的观点去做这件事。认为你会发送消息然后通过让CL做某事来做出回应是合乎逻辑的。这不是服务的目的。基本上,您设置了位置管理器并让它继续。
您可以从我在GitHub上的存储库中使用的一些模式中受益。
它在一年内没有更新,我不记得我学到的所有工作,但它已经为我提供了坚实的工作,因为我没有必要弄清楚它。
在该示例之后,您将停止并启动,或切换到区域或重要位置更改,并根据应用程序状态监控所有更改。无需互动。
您的位置事件按来当,背景或无处理。
在您的远程通知回复中,您只会阅读最新的位置信息或您需要的任何信息,并根据您的意图行事。你不在这里调用startUpdatingLocation。如果您在后台使用位置服务,则应该首先停止它。
编辑 - 正确使用到期处理程序块
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
__block UIBackgroundTaskIdentifier bgTask =0;
UIApplication *app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
// Do something here. Perhaps you'll log the error or respond with some fall back
// This block will only be run if the handler expires without having been ended
// In that case, you need to end it now or you will crash
If (bgTask != UIBackgroundTaskInvalid) {
[app endBackgroundTask:bgTask];
[bgTask = UIBackgroundTaskInvalid];
}
}];
// This is where the code you intend to run in the background starts
[self.locationManager startUpdatingLocation];
// Now tell the system you are finished, ending background task normally before exit
If (bgTask != UIBackgroundTaskInvalid) {
[app endBackgroundTask:bgTask];
[bgTask = UIBackgroundTaskInvalid;
}
}
答案 2 :(得分:0)
方法beginBackgroundTaskWithExpirationHandler:
为应用程序提供了时间,但这并不意味着任务可以永久运行。
如崩溃日志中所述,您的应用程序已被杀死,因为您显然正在耗尽时间
您应该获得相同的结果,只需要更新位置而不包装到到期处理程序中。
我记得在旧系统中我通过使用区域监控触发后台位置更新来管理类似的东西。
[编辑]
为了在玩位置时获得最佳效果,我建议你使用真实的设备,也许你是。