Sugestões de melhorias em um service de track location

Pessoal criei um serviço para pegar as localizações do usuário de tempos e tempos, só que as vezes ele para de pegar a localização talvez por que são viagens feitas na zona rural.
Depois dessa perda ele não volta a pegar a localização mesmo voltado para a cidade. O que devo fazer para contornar esse problema, desde já agradeço, segue o código do serviço:

public class TrackerService extends Service implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,LocationListener{

private static final String LogCat = "DIGICERTO Track";
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
    // Location updates intervals in sec
private static int UPDATE_INTERVAL = 0; // 10 sec
private static int FATEST_INTERVAL = 0; // 5 sec
private static int DISPLACEMENT = 30; // 10 meters
private ArrayList<Location> storedLocation;
private boolean isTracking = false;
public Location mLastLocation;
private ViagemRepository viagemRepository;
private PadraoRepository padraoRepository;
private ParametroRepository parametroRepository;
private Padrao padrao;
private Arquivo arquivo;
private Parametro parametro;
String dataPadrao;
@Override
public void onCreate() {
	super.onCreate();
	padraoRepository = new PadraoRepository(getApplicationContext());
	viagemRepository = new ViagemRepository(getApplicationContext());
	parametroRepository = new ParametroRepository(getApplicationContext());
	

 parametro = parametroRepository.buscaPorId(1);
	if(parametro.getTempoUpdateGps()> 0){
		UPDATE_INTERVAL = parametro.getTempoUpdateGps();
		FATEST_INTERVAL = parametro.getTempoUpdateGps()/2;
	}else{
		UPDATE_INTERVAL = 30000;
		FATEST_INTERVAL = 15000;
	}
	
	
	callConnection();
	createLocationRequest();
	String log = "Reiniciou o serviço";
	arquivo = new Arquivo(getApplicationContext(),parametro.getModoColeta().getModoColeta());
	padraoRepository = verificaPadrao();
	
	Padrao padrao = padraoRepository.ultimoPadrao();
	 
			log(log);
	
}


@Override
public void onDestroy() {
	super.onDestroy();
//	padraoRepository.fechar();
//	viagemRepository.fechar();
	
	
	if(mGoogleApiClient!=null){
		stopLocationUpdates();
	}
	
	String log ="Finalizou serviço.....\r\n";
	log(log);
	
}
	


public int onStartCommand(Intent intent,int flags,int startId){
	if(intent != null){
		
	}
	return super.onStartCommand(intent, flags, startId);
}


public synchronized void callConnection(){
	  mGoogleApiClient = new GoogleApiClient.Builder(this).
			  addOnConnectionFailedListener(this)
			  .addConnectionCallbacks(this)
			  .addApi(LocationServices.API)
			  .build();
	  mGoogleApiClient.connect();
 }


public void createLocationRequest() {
	storedLocation = new ArrayList<Location>();
	
	mLocationRequest = new LocationRequest();
	mLocationRequest.setInterval(UPDATE_INTERVAL);
	mLocationRequest.setFastestInterval(FATEST_INTERVAL);
	mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}

public void startTracking(){
	startLocationUpdates();
	Log.i(LogCat, "Tracking iniciado......");

	String log =" Tempo maximo: "+UPDATE_INTERVAL+" Tempo Minimo: "+FATEST_INTERVAL+"\r\n";

	Log.i("DIGICERTO","Tempo maximo: "+UPDATE_INTERVAL+" Tempo Minimo: "+FATEST_INTERVAL);
	Log.i("DIGICERTO", "Tracking serviço rodando......");
	log += "Tracking serviço rodando......\r\n";
	
	isTracking = true;
	//timer.scheduleAtFixedRate(new mainTask(),0,UPDATE_INTERVAL);
	log(log);
}

public void stopTracking(){
	stopLocationUpdates();
	Log.i(LogCat, "Parando Tracking");
	
	isTracking = false;
	
	String log = " Parando Tracking\r\n";
	log(log);
	
	
}

public boolean isTracking(){
	return isTracking;
}

protected void startLocationUpdates() {
	//createLocationRequest();
	LocationServices.FusedLocationApi.requestLocationUpdates(
			mGoogleApiClient, mLocationRequest, this);
	
	String log = " Iniciou updates de localizacoesr\n";
	log(log);
}

protected void stopLocationUpdates() {
	LocationServices.FusedLocationApi.removeLocationUpdates(
			mGoogleApiClient, this);
	
	String log = " Parou updates de localizacoes.\r\n";
	log(log);
	
}

@Override
public void onLocationChanged(Location location) {
	if (location != null) {
		Log.i(LogCat, "Novo Local Adicionado: " + location.getLatitude()
				+ " " + location.getLongitude());
		storedLocation.add(location);
		mLastLocation = location;

		padraoRepository = verificaPadrao();

		if (padraoRepository.ultimoPadrao() != null) {
			salvarLocalizacoesViagem(location,
					padraoRepository.ultimoPadrao());
		}

	} 

}

private PadraoRepository verificaPadrao(){
	PadraoRepository pad;
	if(padraoRepository==null){
		pad = new PadraoRepository(getApplicationContext());
	}else{
		pad = padraoRepository;
	}
	return pad;
}

private ViagemRepository verificaViagem(){
	ViagemRepository viag;
	if(viagemRepository == null){
		viag = new ViagemRepository(getApplicationContext());
	}else{
		viag = viagemRepository;
	}
	return viag;
}

private void salvarLocalizacoesViagem(Location location, Padrao padrao) {
	viagemRepository = verificaViagem();
	Viagem ultimaViagem = viagemRepository
			.listarUltimoRegistroViagem(padrao);

	double totalDistance = 0.0;
	GPSUtil gps = new GPSUtil();

	Viagem viagem = new Viagem();
	viagem.setPadrao(padrao);
	Calendar calendar = Calendar.getInstance();
	viagem.setDataHora(calendar);
	
	if (location != null) {
		viagem.setLatitude(location.getLatitude());
		viagem.setLongitude(location.getLongitude());
		viagem.setVelocidade(location.getSpeed());

		if (ultimaViagem.getLatitude() != 0
				&& ultimaViagem.getLongitude() != 0) {

			double distancia = gps.calcGeoDistance(
					ultimaViagem.getLatitude(),
					ultimaViagem.getLongitude(), location.getLatitude(),
					location.getLongitude())
					* gps.multipliers[2];
			Location antigolocation = new Location("");
			antigolocation.setLatitude(ultimaViagem.getLatitude());
			antigolocation.setLongitude(ultimaViagem.getLongitude());

			float distancia2 = location.distanceTo(antigolocation);

			Log.d("DIGICERTO", "Latitude: " + ultimaViagem.getLatitude()
					+ " " + ultimaViagem.getLongitude() + "\nULTIMA: "
					+ ultimaViagem.getKmPercorrido());

			Log.d("DIGICERTO",
					"DataHora:"
							+ DateUtil.timeMilisToString(viagem
									.getDataHora().getTimeInMillis(),
									"dd-MM-yy HH:mm")
							+ "\n"
							+ "DATA HORA GPS: "
							+ DateUtil.timeMilisToString(location.getTime())
							+ "\n" + "Latitude: " + viagem.getLatitude()
							+ "\n" + "Longitude: " + viagem.getLongitude()
							+ "\n" + "Velocidade: "
							+ viagem.getVelocidade() * 2.2369 + "\n"
							+ "\n" + "Acurracy: " + location.getAccuracy()
							+ "\n"

			);

			Log.d("DIGICERTO", "Distancia: " + distancia + " " + distancia2);

			if (distancia > 0.010 && location.getAccuracy() < 500.0f) {
				totalDistance = ultimaViagem.getKmPercorrido() + distancia;
				viagem.setKmPercorrido(totalDistance);
				Log.d("DIGICERTO", "SOMADO: " + totalDistance);
				viagemRepository.inserir(viagem);
			}
		} else {
			double distancia = gps.calcGeoDistance(padrao.getLatitude(),
					padrao.getLongitude(), location.getLatitude(),
					location.getLongitude())
					* gps.multipliers[2];
			viagem.setKmPercorrido(distancia);
			viagemRepository.inserir(viagem);
		}

	} else {
		viagem.setKmPercorrido(ultimaViagem.getKmPercorrido());
		viagem.setLatitude(ultimaViagem.getLatitude());
		viagem.setLongitude(ultimaViagem.getLatitude());
		viagem.setVelocidade(0);
		viagemRepository.inserir(viagem);
	}

}

public int getLocationCount(){
	return storedLocation.size();
}

public Location getLocation(){
	return mLastLocation;
}

public ArrayList<Location> getListLocation(){
	return storedLocation;
}

    
@Override
public IBinder onBind(Intent intent) {
    return new TrackerBinder(this);
}


@Override
public void onConnectionFailed(ConnectionResult result) {
	Log.i(LogCat, "falha location: "+result.getErrorCode());
	
	String log =" Falha location  "+result +"+\r\n";
	log(log);
	
}


@Override
public void onConnected(Bundle connectionHint) {
	Log.i(LogCat, "connectado");		
	String log =" Conectou com o gps\r\n";		
	
	Location location = LocationServices
            .FusedLocationApi
            .getLastLocation(mGoogleApiClient);		
	
	startLocationUpdates();
    if(location != null){
        log +=location.getLatitude() + " "+location.getLongitude()+"if(location != null)\r\n";           
    }else{
    	log +="Erro na localizacao\r\n";
    }		
    log(log);        
	
}



@Override
public void onConnectionSuspended(int cause) {
	mGoogleApiClient.connect();
	Log.i(LogCat, "suspenso - inicado");
	String log = "suspenso - inicado "+cause;
	
	log(log);
	
}


private void log(String newLog){
	
	Calendar calendar = Calendar.getInstance();
	String data = DateUtil.timeMilisToString(calendar.getTimeInMillis(),"dd-MM-yyyy hh:mm");
	String log = data+" "+newLog;		
	try {
		arquivo.WriteFile(log,parametro.getPastaDigiCerto(),"log","log.ath");
	} catch (FileNotFoundException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
}

}

Jose Rodrigues, beleza?

Me das umas dicas.
Como você salva a localização? Banco?
Você envia de tempos em tempos para um servidor?

Dê uma olha no tópico abaixo, estou com muito dificuldade aqui de implementar uma logica segura e eficiente no sistema de AFV para acompanhar a equipe.

http://www.guj.com.br/t/localizacao-usuario-duvidas/356036

Obrigado.

No meu caso, eu decidir usar uma lib para fazer esse serviço, para não ter que criar a “roda”, no caso escolhi uma que trabalhasse com o Location Manager, porque como os aparelhos que usam o app, dificilmente irão ter acesso a red de internte, teve melhores resultados do que o Fused Provider.
Da uma olhada no Android Arsenal, la tem algumas que pode te ajudar, https://android-arsenal.com/tag/55?sort=created.
A lib no caso só faz o trabalho de buscar a localização, hoje utilizo o Service + BroadCast Receiver +Alarm Manager, que faz essa busca de tempos em tempos, uso todos porque as vezes o Android pode fechar apps em segundo plano. Além disso também salvo os dados no banco sqlite, porque na minha lógica de negócio, ele só gera um arquivo kml, não envio localizações para servidor.

Jose, mais uma dica.

O problema que estamos encontrando é que o APP monitora a equipe de externa e muitas das vezes em visitas aos clientes estão dentro do prédio/imovel do cliente e ai a localização “sem perde”, mesmo que defino uma distancia de 70m para atualizar as coordenadas (intervalodsetSmallestDisplacement()), uma precisão menor que 30 (getAccuracy()) ou uma distancia de 100m entre a ultima e a atual localização obtida, o sistema acabando que gravando no banco e quando é apresentando no mapa a rota fica pontuada vários pontos no mesmo cliente. Como resolver isso? Não queria aumentar as distancia.

Qual lib você está utilizando do Android Arsenal? Não utilizei/testei nenhuma delas ainda, estou utilizando no app o Fused Provider. Mas vou testa-las.

A minha regra de negocio é parecido com a sua, estou utilizando Service + BroadCast + FCM e gravando no banco SQLite e de tempos em tempos envio a localização para o servidor para o servidor.

vlw.