Serviços de localização em segundo plano que não funcionam no iOS 7

Recentemente, atualizei meus dispositivos iOS para usar o iOS 7. Um dos apps que estamos desenvolvendo usa serviços de localização em segundo plano para rastrear a localização do dispositivo e todos os nossos testadores relataram que o aplicativo não parece mais rastrear em segundo plano no iOS 7

Verificamos que o plano de fundo para o aplicativo está habilitado nas configurações do dispositivo e a versão anterior funcionou perfeitamente no iOS 6. Mesmo se o dispositivo estivesse em ciclo, o aplicativo seria reiniciado após uma atualização de local.

Há algo mais que precisa ser feito para que isso funcione no iOS 7?

Peço desculpas pelo atraso em postar a solução. Eu tenho estado ocupada nos últimos meses e fui pego com minha vida pessoal até que eu me esqueci deste tópico. Aqui está a solução que usei para obter localização contínua a partir de dispositivos iOS 7, independentemente de estar em primeiro ou segundo plano.

Você pode encontrar a solução completa e a explicação do blog e também do github: –

  1. Programação de atualização de localização em segundo plano para iOS 7 e 8

  2. Projeto Github: Programação de atualização de localização em segundo plano para iOS 7 e 8

Métodos e Explicação: –

  1. Eu reinicio o gerenciador de localização a cada 1 minuto na function didUpdateLocations

  2. Eu permito que o gerenciador de localização obtenha os locais do dispositivo por 10 segundos antes de desligá-lo (para economizar bateria).

Código parcial abaixo: –

-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{ for(int i=0;i 30.0) continue; //Select only valid location and also location with good accuracy if(newLocation!=nil&&theAccuracy>0 &&theAccuracy<2000 &&(!(theLocation.latitude==0.0&&theLocation.longitude==0.0))){ self.myLastLocation = theLocation; self.myLastLocationAccuracy= theAccuracy; NSMutableDictionary * dict = [[NSMutableDictionary alloc]init]; [dict setObject:[NSNumber numberWithFloat:theLocation.latitude] forKey:@"latitude"]; [dict setObject:[NSNumber numberWithFloat:theLocation.longitude] forKey:@"longitude"]; [dict setObject:[NSNumber numberWithFloat:theAccuracy] forKey:@"theAccuracy"]; //Add the vallid location with good accuracy into an array //Every 1 minute, I will select the best location based on accuracy and send to server [self.shareModel.myLocationArray addObject:dict]; } } //If the timer still valid, return it (Will not run the code below) if (self.shareModel.timer) return; self.shareModel.bgTask = [BackgroundTaskManager sharedBackgroundTaskManager]; [self.shareModel.bgTask beginNewBackgroundTask]; //Restart the locationMaanger after 1 minute self.shareModel.timer = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:@selector(restartLocationUpdates) userInfo:nil repeats:NO]; //Will only stop the locationManager after 10 seconds, so that we can get some accurate locations //The location manager will only operate for 10 seconds to save battery NSTimer * delay10Seconds; delay10Seconds = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(stopLocationDelayBy10Seconds) userInfo:nil repeats:NO]; } 

Atualização em maio de 2014 : recebi algumas solicitações para adicionar códigos de amostra ao enviar o local ao servidor por um determinado intervalo de tempo. Eu adicionei os códigos de amostra e também combinei uma correção para o BackgroundTaskManager para resolver uma falha de fundo em execução durante um longo período de tempo. Se você tiver alguma dúvida, é bem-vindo para se juntar a nós para uma discussão aqui: Programação de atualização de localização em segundo plano para iOS 7 com atualização de local para discussão do servidor

Atualização de janeiro de 2015 : se você deseja obter a atualização de local mesmo quando o aplicativo é suspenso, consulte: Como obter atualizações de local para iOS 7 e 8 mesmo quando o aplicativo é suspenso

Se você observar o vídeo nº 204 da WWDC 2013 – O que há de novo na multitarefa pdf, a página 15 menciona claramente que os aplicativos não serão iniciados em segundo plano se o usuário o eliminar do alternador de aplicativos. Por favor, veja a imagem,

insira a descrição da imagem aqui

Acho que eles fizeram uma otimização (provavelmente usando sensores de movimento), para detectar o posicionamento estacionário “relativamente” do telefone e parar as atualizações de localização. Isso é apenas uma especulação, mas meus testes atualmente mostram:

  1. Iniciando atualizações de localização; (testado com precisão de 10 e 100 metros, 3 vezes cada)
  2. Desligue a canvas do dispositivo para colocar o aplicativo em segundo plano.
  3. Deixe o dispositivo parado (por exemplo, em uma mesa) por 30 min.

Os dados que eu registro mostram a parada de atualizações geográficas após ~ 15m e 30s. Com isso, todos os outros processamentos em background que você fizer também serão encerrados.

Meu dispositivo é o iPhone 5 com o iOS 7.

Tenho 95% de certeza, este não foi o caso no iOS 6 / 6.1. Onde obter atualizações geográficas com precisão de 100 m costumava dar a você praticamente uma execução contínua em segundo plano.

Atualizar

Se você reiniciar o gerenciador de locais a cada 8 minutos, ele deverá ser executado continuamente.

Atualização 2

Eu não testei isso mais recentemente, mas é assim que eu reiniciei quando escrevi o post. Espero que isto seja útil.

 - (void)tryRestartLocationManager { NSTimeInterval now = [[NSDate date] timeIntervalSince1970]; int seconds = round(floor(now - locationManagerStartTimestamp)); if ( seconds > (60 * 8) ) { [locationManager stopUpdatingLocation]; [locationManager startUpdatingLocation]; locationManagerStartTimestamp = now; } } 

Um dos meus aplicativos para iOS precisa enviar a atualização de localização para o servidor em intervalos regulares e seguir a abordagem trabalhada para nós ….

A partir do iOS 7:

  • um aplicativo já deve estar usando serviços de localização (startUpdatingLocation) ANTES de ter sido em segundo plano para que os usuários qualificados para o tempo de execução em segundo plano
  • o tempo limite do período de carência de fundo foi reduzido de 10 minutos para 3 minutos
  • parar as atualizações de localização (via stopUpdatingLocation) iniciará a contagem de backgroundTimeRemaining de 3 minutos
  • iniciar as atualizações de localização enquanto já está em segundo plano não redefinirá o backgroundTimeRemaining

Portanto, NÃO PARE as atualizações de local a qualquer momento … Em vez disso, prefira usar a precisão necessária (localização perfeita versus localização aproximada). Localização grosseira não consome muita bateria … por isso esta solução resolve o seu problema.

Depois de pesquisar muito on-line, encontrei um link que fornece uma solução viável para o iOS 7. A solução é a seguinte:

  • Enquanto o aplicativo ainda está em primeiro plano, inicie as atualizações de localização (startUpdatingLocation), mas defina os filtros de precisão e distância para atualizações muito específicas (por exemplo, 3 km). É importante fazer isso em primeiro plano (em applicationDidEnterBackground é tarde demais).
  • Quando é necessária uma resolução de baixa granularidade, defina temporariamente os filtros de precisão e distância para obter a melhor localização possível e, em seguida, reverta-os de volta aos valores com granularidade de processamento – mas nunca pare as atualizações de localização.
  • Como as atualizações de localização estão sempre ativadas, o aplicativo não será suspenso quando for para o segundo plano.

E certifique-se de adicionar o seguinte à “localização” do Info.plist do seu aplicativo à chave “serviços de localização” e “gps” do UIBackgroundModes à chave UIRequiredDeviceCapabilities

Créditos: http://gooddevbaddev.wordpress.com/2013/10/22/ios-7-running-location-based-apps-in-the-background/

Eu encontrei outro segmento Iniciar Gerenciador de Localização no iOS 7 da tarefa em segundo plano Sash mencionou que

Eu encontrei o problema / solução. Quando é hora de iniciar o serviço de localização e interromper a tarefa em segundo plano, a tarefa em segundo plano deve ser interrompida com um atraso (configuro 1 segundo). Caso contrário, o serviço de localização não começará.

Alguém pode tentar isso e verificar?

Nikolay, você pode colar seu código aqui? Tentei reiniciar o gerenciador de localização a cada 8 minutos, mas ele não é executado continuamente.

Atualizar:

Depois de pesquisar Alta e Baixa, encontrei a Solução do Fórum da Apple!

No iOS 7, você não pode iniciar o serviço de localização em segundo plano . Se você quiser que o serviço de localização continue sendo executado em segundo plano, será necessário iniciá-lo em primeiro plano e ele continuará sendo executado em segundo plano.

Se você fosse como eu, pare o serviço de localização e use o timer para reiniciá-lo em segundo plano, ele não funcionará.

Para obter informações mais detalhadas, você pode assistir aos primeiros 8 minutos do vídeo 307 do WWDC 2013: https://developer.apple.com/wwdc/videos/

Atualização de fevereiro de 2014: posso obter o local continuamente do dispositivo usando o iOS 7 após vários meses de tentativas. Você pode ver a resposta completa aqui: Serviços de localização em segundo plano que não funcionam no iOS 7

O ícone na barra de status está ativado? É um comportamento estranho que eu também tive. Cheque minha pergunta: startMonitoringSignificantLocationChanges mas depois de algum tempo didUpdateLocations não é mais chamado

Descobri que as mudanças significativas de localização estavam ativas, mas simplesmente parar e reiniciar o serviço (para alterações significativas) não estava acionando novos locais.