【问题标题】:recieving location updates after app is terminated应用程序终止后接收位置更新
【发布时间】:2023-03-11 18:24:01
【问题描述】:

我需要始终跟踪用户位置(但不要耗尽电池电量)。 我了解在应用终止后获取更新的唯一方法是使用 startMonitoringSignificantLocationChanges。

来自 Apple 关于 startMonitoringSignificantLocationChanges 的位置感知编程指南:

如果您启动此服务并且您的应用程序随后 终止,系统自动重新启动应用程序到 新事件到达时的背景。在这种情况下,选项 传递给应用程序的字典:didFinishLaunchingWithOptions: 您的应用程序委托的方法包含密钥 UIApplicationLaunchOptionsLocationKey 来表明你的 由于位置事件而启动了应用程序。 重新启动后, 您仍然必须配置一个位置管理器对象并调用它 方法继续接收位置事件。当你重新启动 位置服务,当前事件被传递给您的代表 立即地。此外,您所在位置的 location 属性 manager 对象甚至填充了最新的位置对象 在您开始定位服务之前。

如果有人可以在代码中演示(举例)我应该使用哪些方法,我会很高兴

在下面的代码中,我想: - 在 appdelegate 启动位置管理器,该管理器对重要的监视器更改更新和启动日期进行管理。 - 在 didUpdateToLocation 我正在调用 stopupdating - 在 didFinishLaunchingWithOptions 中,当我检查是否有 UIApplicationLaunchOptionsLocationKey 以了解我是否在后台并由于重要的监视器位置更新而启动。 - 如果是这样,我再次调用 startMonitoringSignificantLocationChanges(不知道为什么......) 并开始一个 UIBackgeoundTaskIdentifier 来调用 startupdating 方法。

LocationController.m : 
+ (LocationController*)sharedInstance {
    @synchronized(self) {
        if (sharedCLDelegate == nil) {
            [[self alloc] init];
        }
    }
    return sharedCLDelegate;
}

- (id)init
{
    self = [super init];
    if (self != nil) {
        self.locationManager = [[[CLLocationManager alloc] init] autorelease];
        self.locationManager.delegate = self;
        self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
        [self.locationManager startUpdatingLocation];
        [self.locationManager startMonitoringSignificantLocationChanges];

    }
    return self;
}
- (void) startMonitoringSignificantLocationChanges
{
    [self.locationManager startMonitoringSignificantLocationChanges];
}
- (void) stopMonitoringSignificantLocationChanges
{
    [self.locationManager stopMonitoringSignificantLocationChanges];
}
-(void) start{
    [self.locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager 
    didUpdateToLocation:(CLLocation *)newLocation 
           fromLocation:(CLLocation *)oldLocation{
    if ( abs([newLocation.timestamp timeIntervalSinceDate: [NSDate date]]) < 30) {
        self.lastLocation = newLocation;
        [self updateLocation]; //sending location to server
        [self.locationManager stopUpdatingLocation];
    }
}
- (void)locationManager:(CLLocationManager*)manager
       didFailWithError:(NSError*)error{
    [self.locationManager stopUpdatingLocation];
}

AppDelegate.h : 

@interface AppDelegate : NSObject <UIApplicationDelegate> {
    UIBackgroundTaskIdentifier bgTask;
}

AppDelegate.m : 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
        id locationValue = [launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey];
        if (locationValue) {
            [[LocationController sharedInstance] startMonitoringSignificantLocationChanges];
            UIApplication *app  = [UIApplication sharedApplication];
            bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ 
                [app endBackgroundTask:bgTask]; 
                bgTask = UIBackgroundTaskInvalid;
            }];
            [[LocationController sharedInstance] start]; //startupdating
            return YES;
        }
    else { 
            [[LocationController sharedInstance] init];
    }
}
-(void) applicationDidEnterBackground:(UIApplication *) application
{
    NSLog(@"entered background Mode");
}

-(void) applicationDidBecomeActive:(UIApplication *) application
{
    NSLog(@"application Did Become Active");
}

谢谢。

【问题讨论】:

    标签: cllocationmanager cllocation


    【解决方案1】:

    使用你的课程,这就是我要做的。

    在您的 AppDelegate.m 中,当您的应用程序处于前台或后台时,我会移动 CLLocationManager 以在前台/后台运行以匹配。我这样做的原因是因为如果 CLLocationManager 在应用程序处于后台时没有移动到后台,则不会向 CLLocationManager 的回调发送位置更新

    - (void)applicationDidEnterBackground:(UIApplication *) application {
        [[LocationController sharedInstance] stop];
        [[LocationController sharedInstance] startMonitoringSignificantLocationChanges];
        NSLog(@"entered background Mode");
    }
    
    - (void)applicationDidBecomeActive:(UIApplication *) application {
        [[LocationController sharedInstance] stopMonitoringSignificantLocationChanges];
        [[LocationController sharedInstance] start];
        NSLog(@"application Did Become Active");
    }
    

    假设您的应用程序随后移至后台,一段时间后,iOS 认为它使用了过多的内存并终止了您的应用程序。

    几分钟后,iOS 会收到位置更新,并重新启动您的应用,让它知道它是由于定位服务而重新启动的。然后您需要重新启动后台定位服务,因为这将是您的应用程序必须这样做的唯一机会。

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
        if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey]) {
            [[LocationController sharedInstance] startMonitoringSignificantLocationChanges];
        }
        return YES;
    }
    

    哦,还有最后一个变化,我不知道为什么在您的 locationManager:didUpdateToLocation:fromLocation: 方法中您要停止定位服务,因为当您这样做时,没有更多的更新通过。让它继续运行,然后每次发生位置更改时,您都可以将其发送到服务器。

    - (void)locationManager:(CLLocationManager *)manager 
        didUpdateToLocation:(CLLocation *)newLocation 
               fromLocation:(CLLocation *)oldLocation {
    
        if ( abs([newLocation.timestamp timeIntervalSinceDate: [NSDate date]]) < 30) {
            self.lastLocation = newLocation;
            [self updateLocation]; //sending location to server
    
    }
    

    【讨论】:

    • 我得到 if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey]) 条件总是假的。 .如何在启动应用程序期间设置该键?
    猜你喜欢
    • 1970-01-01
    • 2014-09-06
    • 1970-01-01
    • 2016-04-07
    • 2017-07-30
    • 1970-01-01
    • 2014-03-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多