ios - 当应用程序处于后台并且网络连接丢失时,位置更新计时器不起作用?

标签 ios objective-c core-location background-process

要求:我想每 2 分钟向服务器发送一次位置详细信息。为此,我使用了 2 分钟的计时器将位置发送到服务器。 我正在从位置管理器获取当前位置并将坐标发送到服务器。

下面是获取后台位置和处理后台应用刷新的代码

//Background location update
    self.shareModel = [LocationShareModel sharedModel];
    self.shareModel.afterResume = NO;
    UIAlertView * alert;

    //We have to make sure that the Background App Refresh is enable for the Location updates to work in the background.
    if([[UIApplication sharedApplication] backgroundRefreshStatus] == UIBackgroundRefreshStatusDenied){

        alert = [[UIAlertView alloc]initWithTitle:@""
                                          message:@"The app doesn't work without the Background App Refresh enabled. To turn it on, go to Settings > General > Background App Refresh"
                                         delegate:nil
                                cancelButtonTitle:@"Ok"
                                otherButtonTitles:nil, nil];
        [alert show];

    }else if([[UIApplication sharedApplication] backgroundRefreshStatus] == UIBackgroundRefreshStatusRestricted){

        alert = [[UIAlertView alloc]initWithTitle:@""
                                          message:@"The functions of this app are limited because the Background App Refresh is disable."
                                         delegate:nil
                                cancelButtonTitle:@"Ok"
                                otherButtonTitles:nil, nil];
        [alert show];

    } else{

        // When there is a significant change of the location,
        // The key UIApplicationLaunchOptionsLocationKey will be returned from didFinishLaunchingWithOptions
        // When the app is receiving the key, it must reinitiate the locationManager and get
        // the latest location updates

        // This UIApplicationLaunchOptionsLocationKey key enables the location update even when
        // the app has been killed/terminated (Not in th background) by iOS or the user.

        if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey]) {
            DebugLog(@"UIApplicationLaunchOptionsLocationKey");

            // This "afterResume" flag is just to show that he receiving location updates
            // are actually from the key "UIApplicationLaunchOptionsLocationKey"
            self.shareModel.afterResume = YES;

            self.shareModel.anotherLocationManager = [[CLLocationManager alloc]init];
            self.shareModel.anotherLocationManager.delegate = self;
            self.shareModel.anotherLocationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
            self.shareModel.anotherLocationManager.activityType = CLActivityTypeOtherNavigation;

            if([locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
                [self.shareModel.anotherLocationManager requestAlwaysAuthorization];
            }

            [self.shareModel.anotherLocationManager startMonitoringSignificantLocationChanges];
        }
    }



-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{

//    NSLog(@"locationManager didUpdateLocations: %@",locations);

    for(int i=0;i<locations.count;i++){

        CLLocation * newLocation = [locations objectAtIndex:i];
        CLLocationCoordinate2D theLocation = newLocation.coordinate;
        CLLocationAccuracy theAccuracy = newLocation.horizontalAccuracy;

        self.myLocation = theLocation;
        self.myLocationAccuracy = theAccuracy;
        self.myLoc = newLocation;
    }

//    self.shareModel.bgTask = [BackgroundTaskManager sharedBackgroundTaskManager];
//    [self.shareModel.bgTask beginNewBackgroundTask];
}


-(CLLocation *)getCurrentLocation
{
    if(locationManager.location)
    {
        return locationManager.location;
    }
    else if(currentLoaction)
    {
        return currentLoaction;
    }
//    return locationManager.location;
    return self.myLoc;
}



- (void)applicationDidEnterBackground:(UIApplication *)application
{
    firstDate=[NSDate date];
    NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
    [ud setValue:firstDate forKey:@"FirstDate"];
    [ud synchronize];

    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.

    DebugLog(@"applicationDidEnterBackground");
    [self.shareModel.anotherLocationManager stopMonitoringSignificantLocationChanges];

    if([locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
        [self.shareModel.anotherLocationManager requestAlwaysAuthorization];
    }
    [self.shareModel.anotherLocationManager startMonitoringSignificantLocationChanges];

}



- (void)applicationDidBecomeActive:(UIApplication *)application
{

    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    [[UIApplication sharedApplication] ignoreSnapshotOnNextApplicationLaunch];

     DebugLog(@"applicationDidBecomeActive");

    //Remove the "afterResume" Flag after the app is active again.
    self.shareModel.afterResume = NO;

    if(self.shareModel.anotherLocationManager)
        [self.shareModel.anotherLocationManager stopMonitoringSignificantLocationChanges];

    self.shareModel.anotherLocationManager = [[CLLocationManager alloc]init];
    self.shareModel.anotherLocationManager.delegate = self;
    self.shareModel.anotherLocationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
    self.shareModel.anotherLocationManager.activityType = CLActivityTypeOtherNavigation;

    if([locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
        [self.shareModel.anotherLocationManager requestAlwaysAuthorization];
    }
    [self.shareModel.anotherLocationManager startMonitoringSignificantLocationChanges];

}

这是将位置发送到服务器的代码

#pragma pingDriver Location webservice call
-(void)pingdriverLocation
{
    AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    CLLocation *currentLocation = [appDelegate getCurrentLocation];

    if (appDelegate.internetStatus==0)
    {

        NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
        NSMutableArray *driverLocationUpdatesInfo;
        if([userDefaults valueForKey:@"driverLocationInfo"]){
            driverLocationUpdatesInfo = [[NSMutableArray alloc]initWithArray:[CommonUtility fetchArrayFrompListWithKey:@"driverLocationInfo" keyToStoreArrayInDict:@"LocationData"]];
        }else{
            driverLocationUpdatesInfo = [[NSMutableArray alloc]init];
        }
        if(currentLocation){
            [driverLocationUpdatesInfo addObject:currentLocation];
        }
        [CommonUtility storeArrayInpListWithKey:@"driverLocationInfo" keyToStoreArrayInDict:@"LocationData" array:driverLocationUpdatesInfo];
    }
    else
    {
        offlineDriverLocationDataUpload = NO;
        objDriverPing = [[pingDriverLocationwebService alloc]init];
        objDriverPing.delegate = self;
        [objDriverPing pingDriverLocationWebService:self latitude:[NSString stringWithFormat:@"%f",currentLocation.coordinate.latitude] longitude:[NSString stringWithFormat:@"%f",currentLocation.coordinate.longitude]];
    }
}


#pragma mark - ping driver location web service response

-(void)serverResponseForPingDriverLocationWebSerivce:(BOOL)proceed responseDict:(NSDictionary *)responseDict
{
    DebugLog(@"%@",responseDict);
    if(proceed)
    {
        if(offlineDriverLocationDataUpload)
        {
            NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
            if([userDefaults valueForKey:@"driverLocationInfo"])
            {

                NSMutableArray *driverLocationUpdatesInfo = [[NSMutableArray alloc]initWithArray:[CommonUtility fetchArrayFrompListWithKey:@"driverLocationInfo" keyToStoreArrayInDict:@"LocationData"]];

                NSArray *tempArray = [[NSArray alloc]initWithArray:driverLocationUpdatesInfo];

                //to remove object of currentOfflineLocation
                for(CLLocation *location in tempArray)
                {
                    if(location.coordinate.latitude == currentOfflineLocation.coordinate.latitude && location.coordinate.longitude == currentOfflineLocation.coordinate.longitude)
                    {
                        [driverLocationUpdatesInfo removeObject:location];
                        break;
                    }
                }

                currentOfflineLocation = nil;
                [CommonUtility storeArrayInpListWithKey:@"driverLocationInfo" keyToStoreArrayInDict:@"LocationData" array:driverLocationUpdatesInfo];

                if(driverLocationUpdatesInfo.count > 0)
                {
                    [self uploadOfflineDriverLocationData];
                }
                else
                {
                    [userDefaults removeObjectForKey:@"driverLocationInfo"];
                    [userDefaults synchronize];
                    [self pingdriverLocation];
                }
            }
        }
        else
        {
            if([[responseDict valueForKey:@"Next"] integerValue] > 0)
            {

                if([[responseDict valueForKey:@"Notification"] isEqualToString:@"Y"])
                {
                    [[[UIAlertView alloc]initWithTitle:@"Alert" message:[responseDict valueForKey:@"Message"] delegate:nil cancelButtonTitle:nil otherButtonTitles:@"OK", nil] show];
                }


                if (self.locationUpdateTimer) {
                    [self.locationUpdateTimer invalidate];
                }

                if([[responseDict valueForKey:@"Next"] integerValue] != 0)
                {
                    self.locationUpdateTimer = [NSTimer scheduledTimerWithTimeInterval:2 * 60 target:self selector:@selector(updateLocation) userInfo:nil repeats:YES];
                }
            }
        }
    }
}

目前,当应用程序处于前台状态时,它能够每两分钟将位置发送到服务器。当没有互联网连接时,我会存储位置坐标,并在我重新建立连接后将它们上传到服务器。

问题:考虑到我启动了 ping 服务,30 分钟后我的应用程序进入后台状态,连接在该状态下丢失,它在 plist 中存储位置,当我来到前台时,它将所有数据上传到服务器但是之后它不再开始发送位置。

请帮助我,因为我现在没有解决方案。

plist

我也跟着这个教程

location in ios 7 and ios 8

最佳答案

我的猜测是您需要在 applicationDidBecomeActive:
中再次触发计时器 因为你的计时器没有恢复。顺便说一句,请记住首先使您的计时器无效:

[self.locationUpdateTimer invalidate];
self.locationUpdateTimer = [NSTimer scheduledTimerWithTimeInterval:2 * 60 target:self selector:@selector(updateLocation) userInfo:nil repeats:YES];

关于ios - 当应用程序处于后台并且网络连接丢失时,位置更新计时器不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32245583/

相关文章:

ios - 在 obj c 中以编程方式为 subview 添加约束(容器边距的前导和尾随空间)

ios - iOS 上 iBeacon 的首选用例?

swift - 仅过滤距离数据库最近的位置

ios - 错误构建 : Undefined symbol: _SKStoreProductParameterAdNetworkSourceIdentifier

ios - 如何将按钮放在 UIScrollView 的中心?

ios - 如何在ios中点击UITextView打开Pickerview(下拉菜单)?

iphone - 我们可以在位置更改时在后台重新启动应用程序吗?强行退出后台后

ios - 快速解析 UTF8 json 文件不能与 SwiftyJson 一起正常工作

ios - 可本地化的字符串!!!! bundle (路径)尚未加载

ios - 如果 (sqlite3_step(compiledStatement) == SQLITE_ROW) 失败