백그라운드에서 작동하는 iOS 앱을 만들고 3 분마다 사용자 위치를 서버에 게시합니다 (iOS 7의 최대 백그라운드 실행 시간 임). 그러나 한 가지 문제가 있습니다. 배경 서비스가 무작위로 종료됩니다. 때로는 백그라운드에서 2 시간, 때로는 7 시간, 그 다음에는 3 시간 동안 무작위로 실행됩니다.iOS 7 backround 위치 서비스 중지
아래 코드는 오류를 생성합니다. 이 종료 될 때이 표시되면 을 감지 할 수 있습니다. 즉, [UIApplication sharedApplication] .backgroundTimeRemaining이 10 초 미만입니다. 누군가가 어떤 방향으로 향하게 할 수 있습니까? 아니면 그것이 끝나는 이유를 설명 할 수 있습니까? 내 생각 엔 [self.locationManager startUpdatingLocation]이 100 % 안전하지 않습니까? (및 UIApplication sharedApplication .backgroundTimeRemaining을 무제한으로 만드는 방법)
다음은 3 분마다 서버에서받는 "정상적인"로그입니다.
아이폰 5 : startUpdatingLocation 전에 21시 6분 45초 backgroundTimeRemaining : 11.014648
아이폰 5 : startUpdatingLocation 후 21시 6분 45초 backgroundTimeRemaining : 999.000000
아이폰 5 : stopUpdatingLocation 전에 21시 6분 48초 backgroundTimeRemaining : 999.000000
아이폰 5 : stopUpdatingLocation 후 21시 6분 48초 backgroundTimeRemaining : 999.000000
내가 얻을 수있는 모든 도움을 주셔서 감사합니다! 미리 감사드립니다!
코드 :
#import "BetaLocationController.h"
#import "AppDelegate.h"
#import <Parse/Parse.h>
#import "CommunicationController.h"
@interface BetaLocationController() <CLLocationManagerDelegate>
@property UIBackgroundTaskIdentifier bgTask;
@property (strong, nonatomic) CLLocationManager *locationManager;
@property BOOL locationStarted;
@property (strong, nonatomic) CLLocation *myLocation;
@end
@implementation BetaLocationController
- (id)init
{
self = [super init];
if (self) {
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.pausesLocationUpdatesAutomatically = NO;
self.locationManager.activityType = CLActivityTypeOther;
self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
self.locationManager.distanceFilter = kCLDistanceFilterNone;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil];
}
return self;
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation* location = [locations lastObject];
self.myLocation = location;
// NSLog(@"Location: %f, %f", location.coordinate.longitude, location.coordinate.latitude);
}
- (void)didEnterBackground:(NSNotification *) notification
{
[self runBackgroundTask:10];
}
-(void)runBackgroundTask: (int) time{
//check if application is in background mode
if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
//create UIBackgroundTaskIdentifier and create tackground task, which starts after time
__block UIBackgroundTaskIdentifier bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
// [self runBackgroundTask:5];
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSTimer *t = [NSTimer scheduledTimerWithTimeInterval:time target:self selector:@selector(startTrackingBg) userInfo:nil repeats:NO];
[[NSRunLoop currentRunLoop] addTimer:t forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] run];
});
}
}
-(void)startTrackingBg{
[[UIApplication sharedApplication] cancelAllLocalNotifications];
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
NSDate *now = [NSDate date];
localNotification.fireDate = now;
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"HHmm"];
int timeofDay = [[formatter stringFromDate:[NSDate date]] intValue];
localNotification.applicationIconBadgeNumber = timeofDay;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
//set default time
int time = 170;
//if locationManager is ON
if (self.locationStarted == TRUE) {
//Here I can detect the error
if([UIApplication sharedApplication].backgroundTimeRemaining < 10){
[CommunicationController logToParse:[NSString stringWithFormat:@"%@ : Detected error, trying to restart locationservice", [UIDevice currentDevice].name]];
}
//log
[CommunicationController logToParse:[NSString stringWithFormat:@"%@: %@ bgTime before stopUpdatingLocation: %f", [UIDevice currentDevice].name, [NSDate date], [self getBackgroundTime]]];
[self.locationManager stopUpdatingLocation];
self.locationStarted = FALSE;
//log
[CommunicationController logToParse:[NSString stringWithFormat:@"%@: %@ bgTime after stopUpdatingLocation: %f", [UIDevice currentDevice].name, [NSDate date], [self getBackgroundTime]]];
}else{
//start updating location
//log
[CommunicationController logToParse:[NSString stringWithFormat:@"%@: %@ bgTime before startUpdatingLocation: %f", [UIDevice currentDevice].name, [NSDate date], [self getBackgroundTime]]];
[self.locationManager startUpdatingLocation];
self.locationStarted = TRUE;
//Time how long the application will update your location
time = 3;
//log
[CommunicationController logToParse:[NSString stringWithFormat:@"%@: %@ bgTime after startUpdatingLocation: %f", [UIDevice currentDevice].name, [NSDate date], [self getBackgroundTime]]];
}
[self runBackgroundTask:time];
}
-(float)getBackgroundTime{
float bgTime = [[UIApplication sharedApplication] backgroundTimeRemaining];
//If bgtime is over 180, it returns unlimited. In iOS 7, only 3 minutes backgroundtime is available
return bgTime > 180 ? 999 : bgTime;
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
[CommunicationController logToParse:[NSString stringWithFormat:@"%@: %@ LocationManagerDidFail %@: %f", [UIDevice currentDevice].name, [NSDate date], error, [[UIApplication sharedApplication] backgroundTimeRemaining]]];
NSLog(@"Error in locationManager. It Failed: %@", error);
}
-(void)dealloc {
[CommunicationController logToParse:[NSString stringWithFormat:@"%@: %@ got dealloc'ed", [UIDevice currentDevice].name, [NSDate date]]];
NSLog(@"Dealloc in location manager is called");
}
@end
답장을 보내 주셔서 감사합니다. 하지만 리소스 문제라고는 생각하지 않습니다. 앱을 설치하고 실행하는 테스트 용 전화 두 대를 사용하기 때문에 다른 앱은 없습니다. 하지만 배경을 가져 오려고 노력할 것입니다. 내 이해로 언제 깨울 지 알 수 없으며, 내 응용 프로그램의 사용법에 달려 있습니까? – kbjeppesen
맞습니다. Apple 설명서에 따르면, 시작 시간이 소량이라면 앱이 시작될 확률이 높습니다. 또한 Xcode Organizer에서 crashlog를 찾을 수도 있습니다. (iPhone을 연결하고, Xcode에서 창 -> 구성 도우미를 선택하고, 왼쪽 창에서 장치를 선택하고 장치 로그를 클릭하십시오.) – EsbenB
이제 백그라운드 가져 오기가 구현되었으며 훨씬 더 효과적입니다! 전력 소비가 크게 향상되었습니다. 앱이 백그라운드에서 실행되고 있음을 거의 감지 할 수 없습니다! 그러나 우리가 논의한 것처럼 서버가 깨어서 서버에 접속할 때 제어 할 수 없다는 단점이 있습니다. 답변 해주셔서 감사합니다! – kbjeppesen