2014-02-07 3 views
1

У меня есть приложение, которое отправляет данные на сервер. Эти данные публикуются только в том случае, если пользователь находится на определенном расстоянии от местоположения. Я переписал обновления фона в надежде, что позволит мне сохранить фон. Но примерно через 17-18 минут фон перестает выполняться.IOS Неограниченное время фона

Я думал, что это могло быть из-за местоположения locationManager.pauseslocationupdatesautomatically. Но даже когда я устанавливаю значение false, приложение все равно заканчивается примерно на 17 минут. Вот код для моего делегата приложения.

// 
// BAAppDelegate.m 
// Beacon App 
// 
// Created by Huy Ly on 2/10/13. 
// Copyright (c) 2013 Placesign. All rights reserved. 
// 

#import "BAAppDelegate.h" 

@implementation BAAppDelegate 
@synthesize backgroundAnnouncementRevision, backgroundAnnouncementText, backgroundOfferDescription, backgroundOfferName, backgroundOfferPrice, backgroundOfferRevision, isAnnouncing, isOffering, locationManager, targetLocation, currentLocation, beaconTimer; 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    // Override point for customization after application launch. 
    return YES; 
} 

- (void)applicationWillResignActive:(UIApplication *)application 
{ 
    NSLog(@"Application will resign active"); 
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 
} 

- (void)applicationDidEnterBackground:(UIApplication *)application 
{ 
    NSLog(@"Application entered background"); 
    // 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. 
    locationManager.distanceFilter = kCLDistanceFilterNone; 
    locationManager.desiredAccuracy = kCLLocationAccuracyBest; 
    [locationManager setPausesLocationUpdatesAutomatically:YES]; 
    [locationManager startUpdatingLocation]; 
    NSLog(@"Starting timer for posting in background"); 
    /* 
    //Runs the Timer on a background task main thread 
    UIApplication *app = [UIApplication sharedApplication]; 


    //create new uiBackgroundTask 
    __block UIBackgroundTaskIdentifier bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ 
     [app endBackgroundTask:bgTask]; 
     bgTask = UIBackgroundTaskInvalid; 
    }];*/ 

    //and create new timer with async call: 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     //run function methodRunAfterBackground 
     beaconTimer = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:@selector(sendBeacon) userInfo:nil repeats:YES]; 
     [[NSRunLoop currentRunLoop] addTimer:beaconTimer forMode:NSDefaultRunLoopMode]; 
     [[NSRunLoop currentRunLoop] run]; 
    }); 

} 

- (void)applicationWillEnterForeground:(UIApplication *)application 
{ 
    NSLog(@"Application entered foreground"); 

    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 
    [beaconTimer invalidate]; 
} 

- (void)applicationDidBecomeActive:(UIApplication *)application 
{ 
    NSLog(@"Application became active"); 

    // 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. 
    [beaconTimer invalidate]; 
} 

- (void)applicationWillTerminate:(UIApplication *)application 
{ 
    NSLog(@"Application will terminate"); 
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 
    [beaconTimer invalidate]; 
} 


-(void) sendBeacon{ 
    NSLog(@"Beacon Background Send Started"); 

    NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults]; 
    if ([[NSUserDefaults standardUserDefaults]valueForKey:@"PlaceID"]== nil) { 
     isAnnouncing = FALSE; 
     isOffering = FALSE; 
    } 

    //Do a single distance check to see if user is still within bounds 
    //Get the current location 
    [locationManager startUpdatingLocation]; 

    //Compare current location with target location 
    CLLocationDistance distance = [currentLocation distanceFromLocation:targetLocation]; 
    distance=distance/1000; 

    //If user is within location boundary, posts to server 
    if (distance < 0.1 || true) { 
     NSLog(@"Background Sent"); 
     //Set Up the NSURL 
     NSString *urlString = [standardUserDefaults valueForKey:@"statusUpdate"]; 
     NSURL *url   = [NSURL URLWithString:urlString]; 
     NSString *jsonString = [[NSString alloc] initWithFormat:@"{\"Announcement\":{\"Text\":\"%@\",\"ElementContext\":{\"Revision\":%@,\"Source\":{\"ID\":0,\"Type\":0}}},\"Offer\":{\"Description\":\"%@\",\"ElementContext\":{\"Revision\":%@,\"Source\":{\"ID\":0,\"Type\":0}},\"Name\":\"%@\",\"Price\":%@},\"OpStatus\":{\"ElementContext\":{\"Revision\":0,\"Source\":{\"ID\":0,\"Type\":0}},\"Value\":0},\"PlaceID\":%@,\"ResourcesOnPremise\":[{\"ElementContext\":{\"Revision\":0,\"Source\":{\"ID\":%@,\"Type\":1}},\"OnPremiseStatus\":2,\"Resource\":{\"ID\":%@,\"Type\":1}}],\"SignalSources\":[{\"LastSignal\":0,\"Source\":{\"ID\":0,\"Type\":0}}]}", backgroundAnnouncementText, backgroundAnnouncementRevision, backgroundOfferDescription, backgroundOfferRevision, backgroundOfferName, backgroundOfferPrice, [[NSUserDefaults standardUserDefaults]valueForKey:@"PlaceID"], [[NSUserDefaults standardUserDefaults]valueForKey:@"UserID"], [[NSUserDefaults standardUserDefaults]valueForKey:@"UserID"]]; 
     NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; 

     //setup the request 
     NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url]; 
     [request setHTTPMethod:@"POST"]; 
     [request setValue:[NSString stringWithFormat:@"%d", [jsonString length]] forHTTPHeaderField:@"Content-Length"]; 
     [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; 
     [request setHTTPBody:jsonData]; 
     NSURLConnection *requestConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; 

     [requestConnection start]; 

    } 
    else{ 
    } 
} 

-(void) locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{ 
    NSLog(@"Location Manager failed with error %@", error); 
} 

-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{ 
    currentLocation = [locations lastObject]; 
    NSLog(@"Manager did update location"); 
} 

-(void)locationManagerDidPauseLocationUpdates:(CLLocationManager *)manager{ 
    NSLog(@"Location Manager Paused"); 
} 

-(void)locationManagerDidResumeLocationUpdates:(CLLocationManager *)manager{ 
    NSLog(@"Location Manager Resumed"); 
} 

@end 

ответ

2

Вы не должны ожидать бесконечного запуска. Если вы - приложение для местоположения, тогда вы должны ожидать, что его вызывают, когда устройство перемещается. Но если устройство не движется, то нет причин для того, чтобы ОС вызывала вас, и это не будет.

Вам необходимо разработать приложение, чтобы он использовал минимальную батарею для достижения желаемого пользователем поведения. С этой целью, если у вас есть граница, о которой вы заботитесь, вы должны настроить регион местоположения, и вы будете разбужены, когда устройство перемещается в или из этого региона. Это намного, намного дешевле, чем постоянный просмотр GPS.

Если пользователь хочет, чтобы вы записывали каждое небольшое движение, то вы можете установить менеджер местоположений так же, как у вас (с kCLLocationAccuracyBest), но вы все равно будете вызываться только при перемещении устройства. Так как это приведет к разрядке аккумулятора, убедитесь, что это единственный способ достичь цели пользователя.

Существует нет способа запросить «неопределенное фоновое время».

+0

Вы имеете в виду сделать 'locationManager.startMonitoringForRegion (region)' внутри обратного вызова 'locationManagerDidPauseLocationUpdates'? ** ИЛИ ** вы имеете в виду сделать что-то вроде UNLocationNotificationTrigger (region: region, repeat: false) '?? Разве вам больше не разрешено делать что-либо, связанное с местоположениями? Думаю, вы говорите, что вам разрешено, а затем, в конце концов, поймать запуск, используя 'UIApplicationLaunchOptionsLocationKey', как и предоставленный ответ [https://stackoverflow.com/questions/27742677/how-to-get-location-updates- для-КСН-7-и-8-даже-когда-The-приложение-это взвешенное/27742678 # 27742678). Это правильно? – Honey

Смежные вопросы