Estou escrevendo um aplicativo que requer atualizações de localização em segundo plano com alta precisão e baixa frequência . A solução parece ser uma tarefa NSTimer em segundo plano que inicia as atualizações do gerenciador de localização, que então é encerrada imediatamente. Esta pergunta já foi feita antes:
Como obtenho uma atualização de localização em segundo plano a cada n minutos em meu aplicativo iOS?
Obter a localização do usuário a cada n minutos após o aplicativo entrar em segundo plano
iOS Não é o problema típico de cronômetro de rastreamento de localização em segundo plano
Temporizador de fundo de longa duração do iOS com modo de fundo "local"
Serviço de segundo plano em tempo integral iOS com base no rastreamento de localização
mas ainda tenho que fazer um exemplo mínimo funcionar. Depois de tentar todas as permutações das respostas aceitas acima, montei um ponto de partida. Inserindo fundo:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
self.bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
NSLog(@"ending background task");
[[UIApplication sharedApplication] endBackgroundTask:self.bgTask];
self.bgTask = UIBackgroundTaskInvalid;
}];
self.timer = [NSTimer scheduledTimerWithTimeInterval:60
target:self.locationManager
selector:@selector(startUpdatingLocation)
userInfo:nil
repeats:YES];
}
e o método delegado:
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
NSLog(@"%@", newLocation);
NSLog(@"background time: %f", [UIApplication sharedApplication].backgroundTimeRemaining);
[self.locationManager stopUpdatingLocation];
}
O comportamento atual é que os backgroundTimeRemaining
decréscimos de 180 segundos para zero (durante o registro do local) e, em seguida, o manipulador de expiração é executado e nenhuma outra atualização de local é gerada. Como modifico o código acima para receber atualizações periódicas de localização em segundo plano indefinidamente ?
Atualização : estou visando o iOS 7 e parece haver alguma evidência de que as tarefas em segundo plano se comportam de maneira diferente:
Inicie o Location Manager no iOS 7 a partir da tarefa em segundo plano
fonte
Respostas:
Parece que
stopUpdatingLocation
é isso que aciona o cronômetro de vigilância em segundo plano, então eu o substituídidUpdateLocation
por:que parece efetivamente desligar o GPS. O seletor para o fundo
NSTimer
torna-se então:Tudo o que estou fazendo é alternar periodicamente a precisão para obter uma coordenada de alta precisão a cada poucos minutos e, como o
locationManager
não foi interrompido,backgroundTimeRemaining
permanece em seu valor máximo. Isso reduziu o consumo de bateria de ~ 10% por hora (com constantekCLLocationAccuracyBest
em segundo plano) para ~ 2% por hora no meu dispositivo.fonte
Eu escrevi um aplicativo usando os serviços de localização, o aplicativo deve enviar localização a cada 10s. E funcionou muito bem.
Basta usar o método " allowDeferredLocationUpdatesUntilTraveled: timeout ", seguindo o documento da Apple.
As etapas são as seguintes:
Obrigatório: registre o modo de plano de fundo para atualizar o local.
1. Crie LocationManger e startUpdatingLocation, com precisão e distância filtrada como desejar:
2. Para manter o aplicativo em execução para sempre usando o método "allowDeferredLocationUpdatesUntilTraveled: tempo limite" em segundo plano, você deve reiniciar a atualizaçãoLocation com o novo parâmetro quando o aplicativo muda para segundo plano, como este:
3. O aplicativo é atualizadoLocations normalmente com "locationManager: didUpdateLocations:" callback:
4. Mas você deve manipular os dados em "locationManager: didFinishDeferredUpdatesWithError:" callback para seu propósito
5. NOTA: Acho que devemos redefinir os parâmetros do LocationManager cada vez que o aplicativo alternar entre o modo de fundo / fundo.
fonte
allowsBackgroundLocationUpdates = YES
erequestAlwaysAuthorization
ourequestWhenInUseAuthorization
. Por exemplo: `CLLocationManager * locationManager = [[CLLocationManager alloc] init]; locationManager.delegate = self; locationManager.allowsBackgroundLocationUpdates = YES; [locationManager requestAlwaysAuthorization]; [locationManager startUpdatingLocation]; `Se você tiver o
UIBackgroundModes
em seu plist comlocation
chave, não precisa usar obeginBackgroundTaskWithExpirationHandler
método. Isso é redundante. Além disso, você está usando-o incorretamente (veja aqui ), mas isso é discutível, já que seu plist está definido.Com
UIBackgroundModes location
o plist, o aplicativo continuará a ser executado em segundo plano indefinidamente apenas enquantoCLLocationManger
estiver em execução. Se você ligarstopUpdatingLocation
enquanto estiver em segundo plano, o aplicativo irá parar e não iniciará novamente.Talvez você possa ligar um
beginBackgroundTaskWithExpirationHandler
pouco antes de ligarstopUpdatingLocation
e, depois de ligar,startUpdatingLocation
pode ligarendBackgroundTask
para o para mantê-lo em segundo plano enquanto o GPS está parado, mas nunca tentei isso - é apenas uma ideia.Outra opção (que eu não tentei) é manter o gerenciador de localização rodando enquanto está em segundo plano, mas assim que você conseguir uma localização precisa, altere a
desiredAccuracy
propriedade para 1000m ou mais para permitir que o chip GPS seja desligado (para economizar bateria). Então, 10 minutos depois, quando precisar de outra atualização de localização, mudedesiredAccuracy
para 100m para ligar o GPS até obter uma localização precisa, repita.Ao ligar
startUpdatingLocation
para o gerente de localização, você deve dar-lhe tempo para obter uma posição. Você não deve ligar imediatamentestopUpdatingLocation
. Nós o deixamos rodar por no máximo 10 segundos ou até obtermos um local de alta precisão não armazenado em cache.Você precisa filtrar os locais em cache e verificar a precisão do local obtido para garantir que atenda à precisão mínima exigida (veja aqui ). A primeira atualização que você obtém pode ter 10 minutos ou 10 dias. A primeira precisão que você obtém pode ser de 3000 m.
Considere o uso de APIs de mudança de local significativa. Depois de receber a notificação de mudança significativa, você pode começar
CLLocationManager
por alguns segundos para obter uma posição de alta precisão. Não tenho certeza, nunca usei os serviços significativos de mudança de local.fonte
CoreLocation
referência da Apple parece recomendar o uso debeginBackgroundTaskWithExpirationHandler
ao processar dados de localização em segundo plano: "Se um aplicativo iOS precisa de mais tempo para processar os dados de localização, ele pode solicitar mais tempo de execução em segundo plano usando o método beginBackgroundTaskWithName: expirationHandler: da classe UIApplication." - developer.apple.com/library/ios/documentation/UserExperience/…locationManagerDidPauseLocationUpdates
. Eu verifiquei esse comportamento 10 vezes!Quando é hora de iniciar o serviço de localização e parar a tarefa em segundo plano, a tarefa em segundo plano deve ser interrompida com um atraso (1 segundo deve ser suficiente). Caso contrário, o serviço de localização não será iniciado. Além disso, o serviço de localização deve ser deixado ligado por alguns segundos (por exemplo, 3 segundos).
Existe um cocoapod APScheduledLocationManager que permite obter atualizações de localização de fundo a cada n segundos com a precisão de localização desejada.
O repositório também contém um aplicativo de exemplo escrito em Swift 3.
fonte
Que tal experimentar com a
startMonitoringSignificantLocationChanges:
API? Ele definitivamente dispara com menos frequência e a precisão é razoavelmente boa. Além disso, tem muito mais vantagens do que usar outraslocationManager
APIs.Muito mais sobre esta API já foi discutido neste link
fonte
This interface delivers new events only when it detects changes to the device’s associated cell towers
Você precisa adicionar o modo de atualização de localização em seu aplicativo, adicionando a seguinte chave em seu info.plist.
didUpdateToLocation
método será chamado (mesmo quando seu aplicativo está em segundo plano). Você pode realizar qualquer coisa com base nesta chamada de métodofonte
Depois do iOS 8, várias mudanças na estrutura CoreLocation relacionadas à busca de plano de fundo e atualizações feitas pela apple.
1) A Apple apresenta a solicitação AlwaysAuthorization para buscar a atualização do local no aplicativo.
2) A Apple introduz backgroundLocationupdates para buscar a localização do fundo no iOS.
Para obter a localização em segundo plano, você precisa habilitar a atualização de localização nos recursos do Xcode.
fonte
Para usar os serviços de localização padrão enquanto o aplicativo está em segundo plano, você precisa primeiro ativar os Modos de segundo plano na guia Recursos das configurações de Destino e selecionar Atualizações de localização.
Ou adicione-o diretamente ao Info.plist .
Então você precisa configurar o CLLocationManager
Objetivo C
Rápido
Ref: https://medium.com/@javedmultani16/location-service-in-the-background-ios-942c89cd99ba
fonte
fonte