Reputation: 31
This is the second time my app was rejected due the GPS background key. Here is the code I am using:
-(void)stopGPS{
[self.locationManagerAll stopUpdatingLocation];
self.locationManagerAll.delegate = nil;
locationManagerAll = nil;
self.cloop = 1;
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setValue:[NSNumber numberWithBool:NO] forKey:@"UpdateLocation"];
[prefs setValue:[NSNumber numberWithInt:0] forKey:@"updationTime"];
[prefs synchronize];
[set.gpsOnOff setOn:NO];
[set.settingsTable reloadData];
[self stopThread];
}
-(void)startGPS{
if ([CLLocationManager locationServicesEnabled]){
if(self.locationManagerAll == nil){
self.locationManagerAll = [[CLLocationManager alloc] init];
self.locationManagerAll.delegate = self;
}
self.locationManagerAll.desiredAccuracy = kCLLocationAccuracyHundredMeters;
self.locationManagerAll.distanceFilter = kCLDistanceFilterNone;
[self.locationManagerAll startUpdatingLocation];
}else {
[set.gpsOnOff setOn:NO];
[set.settingsTable reloadData];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Location Service Disabled"
message:@"To re-enable, please go to Settings and turn on Location Service for this app."
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
}
}
These above functions used to start or stop the GPS location, Here are the implementations for GPS location:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
if ([oldLocation.timestamp timeIntervalSinceNow] < - 5) return;
if (newLocation.horizontalAccuracy > 5.0) return;
if (newLocation.coordinate.latitude == oldLocation.coordinate.latitude && newLocation.coordinate.longitude == oldLocation.coordinate.longitude) return;
NSString *currentLatitude = [[NSString alloc]
initWithFormat:@"%f",
newLocation.coordinate.latitude];
NSString *currentLongitude = [[NSString alloc]
initWithFormat:@"%f",
newLocation.coordinate.longitude];
[prefs setValue:currentLatitude forKey:@"UpdateLocationLati"];
[prefs setValue:currentLongitude forKey:@"UpdateLocationLongi"];
[prefs synchronize];
[currentLatitude release];
[currentLongitude release];
if (self.cloop == 1) {
/*UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"Current location saved." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alert show];
[alert release]; */
self.cloop = 0;
[prefs setValue:[NSNumber numberWithInt:60] forKey:@"updationTime"];
[prefs setValue:[NSNumber numberWithBool:YES] forKey:@"UpdateLocation"];
[prefs synchronize];
[set.gpsOnOff setOn:YES];
[set.settingsTable reloadData];
[self startThread];
}
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
if ([error code] != kCLErrorLocationUnknown) {
[self stopGPS];
UIAlertView *alert = [[UIAlertView alloc] init];
[alert setTitle:@"Location"];
[alert setMessage:@"Unable to get current location"];
[alert setDelegate:self.set];
[alert addButtonWithTitle:@"Cancel"];
[alert addButtonWithTitle:@"Retry"];
[alert show];
[alert release];
}
}
I am also using a thread for timer which update the location on server after every second. AS the timer stop when the app went to background I am using this code to handle this:
- (void)applicationDidEnterBackground:(UIApplication *)application{
/*
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.*/
if ([[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)]) { //Check if our iOS version supports multitasking I.E iOS 4
if ([[UIDevice currentDevice] isMultitaskingSupported]) { //Check if device supports mulitasking
UIApplication *application = [UIApplication sharedApplication]; //Get the shared application instance
__block UIBackgroundTaskIdentifier background_task; //Create a task object
background_task = [application beginBackgroundTaskWithExpirationHandler: ^{
[application endBackgroundTask:background_task];
//Tell the system that we are done with the tasks
background_task = UIBackgroundTaskInvalid; //Set the task to be invalid
//System will be shutting down the app at any point in time now
}];
//Background tasks require you to use asyncrous tasks
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//Perform your tasks that your application requires
//I do what i need to do here.... synchronously...
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
if ([[prefs objectForKey:@"updationTime"] intValue] > 0 && [[prefs objectForKey:@"UpdateLocation"] boolValue]) {
self.backgroundTimer = [NSTimer timerWithTimeInterval:[[prefs objectForKey:@"updationTime"] intValue] target:self selector:@selector(backgroundTriggerTimer) userInfo:nil repeats:YES];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:backgroundTimer forMode:NSRunLoopCommonModes];
[runLoop run];
}
[application endBackgroundTask:background_task];
//End the task so the system knows that you are done with what you need to perform
background_task = UIBackgroundTaskInvalid; //Invalidate the background_task
});
}else if (![[UIDevice currentDevice] isMultitaskingSupported]) {
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
if ([[prefs objectForKey:@"UpdateLocation"] boolValue]){
[self stopGPS];
}
}
}else if (![[UIDevice currentDevice] isMultitaskingSupported]) {
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
if ([[prefs objectForKey:@"UpdateLocation"] boolValue]){
[self stopGPS];
}
}
}
Here is the thread code I am using:
-(void)startThread
{
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
if ([[prefs objectForKey:@"UpdateLocation"] boolValue]) {
self.updateLocation = [[NSThread alloc] initWithTarget:self selector:@selector(setUpTimerThread) object:nil];
[self.updateLocation start];
}
}
-(void)stopThread{
[self.updateLocation cancel];
updateLocation = nil;
[self.gpsTimer invalidate];
}
-(void)setUpTimerThread
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
if ([[prefs objectForKey:@"updationTime"] intValue] > 0) {
self.gpsTimer = [NSTimer timerWithTimeInterval:[[prefs objectForKey:@"updationTime"] intValue] target:self selector:@selector(triggerTimer) userInfo:nil repeats:YES];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:gpsTimer forMode:NSRunLoopCommonModes];
[runLoop run];
}
[pool release];
}
-(void)triggerTimer
{
NSLog(@"***Timer Called after seconds**");
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSString *location = [[[NSString alloc] initWithFormat:@"%f_%f",[[prefs objectForKey:@"UpdateLocationLati"] doubleValue], [[prefs objectForKey:@"UpdateLocationLongi"] doubleValue]] autorelease];
NSString *urlGen = [[[NSString alloc] initWithFormat:@"%@%d/%@",[prefs objectForKey:@"update_user_location"],[[prefs objectForKey:@"USERID"] intValue], location] autorelease];
NSLog(@"urlGen: %@", urlGen);
NSString *rt = [JSONModel stringWithUrl:urlGen];
if (self.alertLoop == 1) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"GPS location has been sent. This alert message will only prompt you once." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alert show];
[alert release];
self.alertLoop = 0;
}
NSLog(@"UPDATE LOCATION : %d", [rt intValue]);
}
I am totally confused. I dont know if I miss something. Can any body please help me out.
Upvotes: 2
Views: 1390
Reputation: 8090
It doesn't look like you missed something but one of the possible reasons for 2.16 rejection is the absence of GPS battery warning in your app description on the app meta in iTunesConnect - "The continued use of GPS may decrease battery life" or something like that.
Upvotes: 5