2013-10-16 1 views
2

내 알고리즘이 다음과 같이 작동합니다.
내 서버의 상태가 변경되면 내 애플리케이션에 원격 알림을 보냅니다. 상태가 일시 중지되거나 실행되지 않음). 그러나 사용자에게 알리기 전에 일부 코드를 실행하고 싶습니다. iOS 7 이전에는 불가능했지만 iOS 7 이상에서는 가능했습니다. (Visit this for further details)시작 위치 서비스 백그라운드에서 iOS7 이상 어느 시점에서든지

실행하려는 코드에는 사용자의 위치를 ​​한 번 추적 한 다음 중지합니다. 그러나 위치 추적을위한 백그라운드 모드는 전경에서 위치 업데이트를 시작해야하며 앱이 백그라운드로 이동하면 CLLocationManager Delegate이 자동으로 위치 업데이트를받습니다. 그러나, 나는 단지 한 시점에서 한 번 추적하고 멈추고 싶습니다.

추신 : 내 서버의 상태는 언제든지 변경 될 수 있습니다. 타이머 나 간격을 사용할 수 없습니다.

+0

@Wain 이걸로 나를 도울 수 있기를 바랍니다. – aMother

답변

0

문제점/해결책을 찾았습니다. 위치 서비스를 시작하고 백그라운드 작업을 중지 할 때 배경 작업을 지연 (1 초 설정)해야합니다. 그렇지 않으면 위치 서비스가 시작되지 않습니다.

또 다른 중요한 알림, iOS 7의 최대 배경 시간은 이제 10 분이 아닌 3 분입니다.

어쩌면 누군가를 도울 것입니다.

편집 :

작은 예제를 작성 후, 나는 위치 서비스도 (내 예에서 3 초) 초 몇 ON 남아있을 것을 발견했다. ".plist"파일에서 UIBackgroundModes를 "location"으로 설정하십시오. 예 :

ScheduledLocationManager.h

#import <Foundation/Foundation.h> 
#import <CoreLocation/CoreLocation.h> 

@interface ScheduledLocationManager : NSObject <CLLocationManagerDelegate> 

-(void)getUserLocationWithInterval:(int) interval ; 

@end 

ScheduledLocationManager.m 당신은 ScheduledLocationManager의 인스턴스를 생성하고 getUserLocationWithInterval 초 간격을 통과 호출해야

#import "ScheduledLocationManager.h" 

int const kMaxBGTime = 170; //3 min - 10 seconds (as bg task is killed faster) 
int const kTimeToGetLocations = 3; 

@implementation ScheduledLocationManager{ 
    UIBackgroundTaskIdentifier bgTask; 
    CLLocationManager *locationManager; 
    NSTimer *checkLocationTimer; 
    int checkLocationInterval; 
    NSTimer *waitForLocationUpdatesTimer; 
} 

- (id)init 
{ 
    self = [super init]; 
    if (self) { 
     locationManager = [[CLLocationManager alloc] init]; 
     locationManager.delegate = self; 
     locationManager.desiredAccuracy = kCLLocationAccuracyBest; 
     locationManager.distanceFilter = kCLDistanceFilterNone; 

     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil]; 
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil]; 
    } 
    return self; 
} 

-(void)getUserLocationWithInterval:(int) interval 
{ 
    checkLocationInterval = (interval > kMaxBGTime)? kMaxBGTime : interval; 
    [locationManager startUpdatingLocation]; 
} 

- (void)timerEvent:(NSTimer*)theTimer 
{ 
    [self stopCheckLocationTimer]; 
    [locationManager startUpdatingLocation]; 

    // in iOS 7 we need to stop background task with delay, otherwise location service won't start 
    [self performSelector:@selector(stopBackgroundTask) withObject:nil afterDelay:1]; 
} 

-(void)startCheckLocationTimer 
{ 
    [self stopCheckLocationTimer]; 
    checkLocationTimer = [NSTimer scheduledTimerWithTimeInterval:checkLocationInterval target:self selector:@selector(timerEvent:) userInfo:NULL repeats:NO]; 
} 

-(void)stopCheckLocationTimer 
{ 
    if(checkLocationTimer){ 
     [checkLocationTimer invalidate]; 
     checkLocationTimer=nil; 
    } 
} 

-(void)startBackgroundTask 
{ 
    [self stopBackgroundTask]; 
    bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ 
     //in case bg task is killed faster than expected, try to start Location Service 
     [self timerEvent:checkLocationTimer]; 
    }]; 
} 

-(void)stopBackgroundTask 
{ 
    if(bgTask!=UIBackgroundTaskInvalid){ 
     [[UIApplication sharedApplication] endBackgroundTask:bgTask]; 
     bgTask = UIBackgroundTaskInvalid; 
    } 
} 

-(void)stopWaitForLocationUpdatesTimer 
{ 
    if(waitForLocationUpdatesTimer){ 
     [waitForLocationUpdatesTimer invalidate]; 
     waitForLocationUpdatesTimer =nil; 
    } 
} 

-(void)startWaitForLocationUpdatesTimer 
{ 
    [self stopWaitForLocationUpdatesTimer]; 
    waitForLocationUpdatesTimer = [NSTimer scheduledTimerWithTimeInterval:kTimeToGetLocations target:self selector:@selector(waitForLoactions:) userInfo:NULL repeats:NO]; 
} 

- (void)waitForLoactions:(NSTimer*)theTimer 
{ 
    [self stopWaitForLocationUpdatesTimer]; 

    if(([[UIApplication sharedApplication ]applicationState]==UIApplicationStateBackground || 
     [[UIApplication sharedApplication ]applicationState]==UIApplicationStateInactive) && 
     bgTask==UIBackgroundTaskInvalid){ 
     [self startBackgroundTask]; 
    } 

    [self startCheckLocationTimer]; 
    [locationManager stopUpdatingLocation]; 
} 

#pragma mark - CLLocationManagerDelegate methods 

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations 
{  
    if(checkLocationTimer){ 
     //sometimes it happens that location manager does not stop even after stopUpdationLocations 
     return; 
    } 

    //TODO: save locations 

    if(waitForLocationUpdatesTimer==nil){ 
     [self startWaitForLocationUpdatesTimer]; 
    } 
} 

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error 
{ 
    //TODO: handle error 
} 

#pragma mark - UIAplicatin notifications 

- (void)applicationDidEnterBackground:(NSNotification *) notification 
{ 
    if([self isLocationServiceAvailable]==YES){ 
     [self startBackgroundTask]; 
    } 
} 

- (void)applicationDidBecomeActive:(NSNotification *) notification 
{ 
    [self stopBackgroundTask]; 
    if([self isLocationServiceAvailable]==NO){ 
     //TODO: handle error 
    } 
} 

#pragma mark - Helpers 

-(BOOL)isLocationServiceAvailable 
{ 
    if([CLLocationManager locationServicesEnabled]==NO || 
     [CLLocationManager authorizationStatus]==kCLAuthorizationStatusDenied || 
     [CLLocationManager authorizationStatus]==kCLAuthorizationStatusRestricted){ 
     return NO; 
    }else{ 
     return YES; 
    } 
} 


@end 

.

+0

현재 검토 중입니다. 그것이 나를 위해 작동하는지 알려 드리겠습니다. – aMother

+0

@aMother가 당신을 어떻게 생각하니? – Guerrix

+0

@ Guerrix 나는 바빴고 그것을 테스트 할 수 없었다. 작동하는지 알려 드리겠습니다. – aMother

관련 문제