在 apple iWatch 中,后台任务未被调用或按计划时间触发
In apple iWatch background task is not getting called or triggering with schedule time
当应用程序在后台触发任务时更新位置。但无法以后台模式执行任务。我的 scheduleBackgroundRefreshWithPreferredDate 示例代码如下
[WKExtension.sharedExtension scheduleBackgroundRefreshWithPreferredDate:[NSDate dateWithTimeIntervalSinceNow:60] userInfo:nil scheduledCompletion:^(NSError * _Nullable error) {
if(error == nil) {
NSLog(@"background refresh task re-scheduling successfuly ");
} else{
NSLog(@"Error occurred while re-scheduling background refresh: %@",error.localizedDescription);
}
}];
在 handleBackgroundTasks:
中安排任务重新安排
- (void)handleBackgroundTasks:(NSSet<WKRefreshBackgroundTask *> *)backgroundTasks
{
for (WKRefreshBackgroundTask * task in backgroundTasks) {
if ([task isKindOfClass:[WKApplicationRefreshBackgroundTask class]]) {
WKApplicationRefreshBackgroundTask *backgroundTask = (WKApplicationRefreshBackgroundTask*)task;
// location update methods schedule as background task
[self startLocationUpdate];
[backgroundTask setTaskCompleted];
} else if ([task isKindOfClass:[WKSnapshotRefreshBackgroundTask class]]) {
WKSnapshotRefreshBackgroundTask *snapshotTask = (WKSnapshotRefreshBackgroundTask*)task;
[snapshotTask setTaskCompletedWithDefaultStateRestored:YES estimatedSnapshotExpiration:[NSDate distantFuture] userInfo:nil];
} else if ([task isKindOfClass:[WKWatchConnectivityRefreshBackgroundTask class]]) {
WKWatchConnectivityRefreshBackgroundTask *backgroundTask = (WKWatchConnectivityRefreshBackgroundTask*)task;
[backgroundTask setTaskCompleted];
} else if ([task isKindOfClass:[WKURLSessionRefreshBackgroundTask class]]) {
WKURLSessionRefreshBackgroundTask *backgroundTask = (WKURLSessionRefreshBackgroundTask*)task;
[backgroundTask setTaskCompleted];
} else {
[task setTaskCompleted];
}
}
}
后台任务方法如下
-(void)startLocationUpdate {
locationMgr = [[CLLocationManager alloc] init];
[locationMgr setDelegate:self];
locationMgr.desiredAccuracy = kCLLocationAccuracyBest;
locationMgr.distanceFilter = kCLDistanceFilterNone;
// locationMgr.allowsBackgroundLocationUpdates = YES;
[locationMgr requestAlwaysAuthorization];
[locationMgr startUpdatingLocation];
[WKExtension.sharedExtension scheduleBackgroundRefreshWithPreferredDate:[NSDate dateWithTimeIntervalSinceNow:60] userInfo:nil scheduledCompletion:^(NSError * _Nullable error) {
if(error == nil) {
NSLog(@"background refresh task re-scheduling successfuly ");
} else{
NSLog(@"Error occurred while re-scheduling background refresh: %@",error.localizedDescription);
}
}];
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray<CLLocation *> *)locations {
NSTimeInterval locationAge = -[[locations lastObject].timestamp timeIntervalSinceNow];
NSLog(@"Location Age : %f",locationAge);
if (locationAge > 5.0) return;
NSLog(@"latitude: %f longitude: %f",[locations lastObject].coordinate.latitude,[locations lastObject].coordinate.longitude);
//NSString *strLocation = [NSString stringWithFormat:@"%f,%f" ,[locations lastObject].coordinate.latitude , [locations lastObject].coordinate.longitude];
NSString *strLocation = @"bgLocation";
NSDictionary *applicationData = [[NSDictionary alloc] initWithObjects:@[strLocation] forKeys:@[@"watchlocation"]];
[[WCSession defaultSession] transferUserInfo:applicationData];
}
后台执行在 watchOS3 上非常困难。有很多限制,即使您成功安排了后台刷新任务,也不能保证 watchOS 会启动它。
根据我深入研究 WWDC 会议和文档后的经验:
- 如果应用程序不在 Dock 中或当前表盘上没有活动的复杂功能,watchOS3 将不会为您的应用程序提供任何后台执行时间
- Dock 中的应用程序的后台刷新任务数量限制为每小时 1 次,具有活动并发症的应用程序每小时 2 次
- 后台执行时间也有限制,如果app超过这个时间,会被watchOS daemon终止
- 一旦您调用
setTaskCompleted
,应用程序将进入挂起状态,因此不应执行代码中的异步 locationManager:didUpdateLocations:
方法
当应用程序在后台触发任务时更新位置。但无法以后台模式执行任务。我的 scheduleBackgroundRefreshWithPreferredDate 示例代码如下
[WKExtension.sharedExtension scheduleBackgroundRefreshWithPreferredDate:[NSDate dateWithTimeIntervalSinceNow:60] userInfo:nil scheduledCompletion:^(NSError * _Nullable error) {
if(error == nil) {
NSLog(@"background refresh task re-scheduling successfuly ");
} else{
NSLog(@"Error occurred while re-scheduling background refresh: %@",error.localizedDescription);
}
}];
在 handleBackgroundTasks:
- (void)handleBackgroundTasks:(NSSet<WKRefreshBackgroundTask *> *)backgroundTasks
{
for (WKRefreshBackgroundTask * task in backgroundTasks) {
if ([task isKindOfClass:[WKApplicationRefreshBackgroundTask class]]) {
WKApplicationRefreshBackgroundTask *backgroundTask = (WKApplicationRefreshBackgroundTask*)task;
// location update methods schedule as background task
[self startLocationUpdate];
[backgroundTask setTaskCompleted];
} else if ([task isKindOfClass:[WKSnapshotRefreshBackgroundTask class]]) {
WKSnapshotRefreshBackgroundTask *snapshotTask = (WKSnapshotRefreshBackgroundTask*)task;
[snapshotTask setTaskCompletedWithDefaultStateRestored:YES estimatedSnapshotExpiration:[NSDate distantFuture] userInfo:nil];
} else if ([task isKindOfClass:[WKWatchConnectivityRefreshBackgroundTask class]]) {
WKWatchConnectivityRefreshBackgroundTask *backgroundTask = (WKWatchConnectivityRefreshBackgroundTask*)task;
[backgroundTask setTaskCompleted];
} else if ([task isKindOfClass:[WKURLSessionRefreshBackgroundTask class]]) {
WKURLSessionRefreshBackgroundTask *backgroundTask = (WKURLSessionRefreshBackgroundTask*)task;
[backgroundTask setTaskCompleted];
} else {
[task setTaskCompleted];
}
}
}
后台任务方法如下
-(void)startLocationUpdate {
locationMgr = [[CLLocationManager alloc] init];
[locationMgr setDelegate:self];
locationMgr.desiredAccuracy = kCLLocationAccuracyBest;
locationMgr.distanceFilter = kCLDistanceFilterNone;
// locationMgr.allowsBackgroundLocationUpdates = YES;
[locationMgr requestAlwaysAuthorization];
[locationMgr startUpdatingLocation];
[WKExtension.sharedExtension scheduleBackgroundRefreshWithPreferredDate:[NSDate dateWithTimeIntervalSinceNow:60] userInfo:nil scheduledCompletion:^(NSError * _Nullable error) {
if(error == nil) {
NSLog(@"background refresh task re-scheduling successfuly ");
} else{
NSLog(@"Error occurred while re-scheduling background refresh: %@",error.localizedDescription);
}
}];
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray<CLLocation *> *)locations {
NSTimeInterval locationAge = -[[locations lastObject].timestamp timeIntervalSinceNow];
NSLog(@"Location Age : %f",locationAge);
if (locationAge > 5.0) return;
NSLog(@"latitude: %f longitude: %f",[locations lastObject].coordinate.latitude,[locations lastObject].coordinate.longitude);
//NSString *strLocation = [NSString stringWithFormat:@"%f,%f" ,[locations lastObject].coordinate.latitude , [locations lastObject].coordinate.longitude];
NSString *strLocation = @"bgLocation";
NSDictionary *applicationData = [[NSDictionary alloc] initWithObjects:@[strLocation] forKeys:@[@"watchlocation"]];
[[WCSession defaultSession] transferUserInfo:applicationData];
}
后台执行在 watchOS3 上非常困难。有很多限制,即使您成功安排了后台刷新任务,也不能保证 watchOS 会启动它。
根据我深入研究 WWDC 会议和文档后的经验:
- 如果应用程序不在 Dock 中或当前表盘上没有活动的复杂功能,watchOS3 将不会为您的应用程序提供任何后台执行时间
- Dock 中的应用程序的后台刷新任务数量限制为每小时 1 次,具有活动并发症的应用程序每小时 2 次
- 后台执行时间也有限制,如果app超过这个时间,会被watchOS daemon终止
- 一旦您调用
setTaskCompleted
,应用程序将进入挂起状态,因此不应执行代码中的异步locationManager:didUpdateLocations:
方法