Solucionado (ver solução)
Solucionado
(ver solução)
13
respostas

Erro ao recuperar uma LatLng através do Geocoder

Estou desenvolvendo meu tcc, onde insiro estabelecimentos de minha base de dados no mapa, e estou me baseando nos cursos do Alura para fazer essa pesquisa através do Geocoder que me trás a Latitude e Longitude de um endereço. Porém estou tendo um problema, esse Geocoder ao fazer o método getFromLocationName() está sempre me retornando nulo para todos os endereço. Antes esta parte estava ok, funcionando normal, não mexi em nada e começou a dar esse problema comigo. Estou quebrando a cabeça e já pesquisei muito para tentar resolver e nada. Segue código:

package br.com.alura.searchdrink.task;

import android.app.ProgressDialog;
import android.content.Context;
import android.location.Address;
import android.location.Geocoder;
import android.os.AsyncTask;
import android.support.annotation.NonNull;
import android.util.Log;
import android.widget.Toast;

import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.firebase.database.ChildEventListener;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.ValueEventListener;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import br.com.alura.searchdrink.R;
import br.com.alura.searchdrink.fragment.MapaFragment;
import br.com.alura.searchdrink.modelo.Bar;

public class TarefaDownloadLocalizacaoBares extends AsyncTask<DatabaseReference, Void, List<Bar>> {

    private final Context context;

    private List<Estabelecimento> estabelecimentos;

    private ProgressDialog progresso;

    public TarefaDownloadLocalizacaoBares(Context context){
        this.context = context;
    }

    @Override
    protected void onPreExecute() {
        Log.i("AsyncTask", "Exibindo ProgressDialog na tela Thread: " + Thread.currentThread().getName());
        progresso = ProgressDialog.show(context, "Por favor aguarde ...",
                "Baixando Estabelecimentos...");
    }

    @Override
    protected List<Bar> doInBackground(DatabaseReference... dbs) {

        estabelecimentos = new ArrayList<>();

        ValueEventListener postListener = pegaEstabelecimentos();
        dbs[0].addValueEventListener(postListener);

        synchronized (estabelecimentos){
            try {
                estabelecimentos.wait();
            } catch (InterruptedException e) {e.printStackTrace();}
        }

        return estabelecimentos;
    }


    @Override
    protected void onPostExecute(List<Estabelecimento> e) {

        if (e.size() != 0) {
            for (Estabelecimento estabelecimento : e) {
                LatLng coordenada = pegaCoordenadaDoEndereco(estabelecimento.getEndereco());
                if (coordenada != null) {
                    MarkerOptions marcador = new MarkerOptions();
                    marcador.position(coordenada);
                    marcador.title(estabelecimento.getNome());
                    marcador.snippet(String.valueOf(estabelecimento.getTelefone()));
                    marcador.icon(BitmapDescriptorFactory.fromResource(R.drawable.copocheio_mapa));
                    MapaFragment.mapa.addMarker(marcador);

                }
            }
        }

        progresso.dismiss();

    }

    private LatLng pegaCoordenadaDoEndereco(String endereco) {

        try{
            Geocoder geocoder = new Geocoder(context);

            List<Address> resultados = geocoder.getFromLocationName(endereco, 1);

            if(!resultados.isEmpty()){
                LatLng posicao = new LatLng(resultados.get(0).getLatitude(),
                        resultados.get(0).getLongitude());
                return posicao;
            }

        }catch(IOException e){
            e.printStackTrace();
        }
        return null;
    }

    @NonNull
    private ValueEventListener pegaEstabelecimentos() {
        return new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {

                synchronized (estabelecimentos) {

                    for (DataSnapshot snapshot : dataSnapshot.getChildren()) {

                        Map<String, Object> map = (HashMap<String, Object>) snapshot.getValue();

                        String nome = String.valueOf(map.get("nome"));
                        String endereco = String.valueOf(map.get("endereco"));
                        String telefone = String.valueOf(map.get("telefone"));
                        String site = String.valueOf(map.get("site"));
                        String email = String.valueOf(map.get("email"));
                        String tipoBar = String.valueOf(map.get("tipoBar"));

                        if (endereco != null) {
                            Estabelecimento estabelecimento = new Estabelecimento(nome, endereco, telefone, site, email, tipoBar);
                            estabelecimentos.add(estabelecimento);
                        }
                    }

                    estabelecimentos.notifyAll();

                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
                // Getting Post failed, log a message
                Log.w("AsyncTask", "loadPost:onCancelled", databaseError.toException());
                // ...
            }
        };
    }
}

Quem puder me ajudar agradeço muito, estou com esse projeto atrasado já

13 respostas

Olá.

Pode alterar seu método "pegaCooordenadaDoEndereco" para fazermos um teste? Deixe o código do bloco try assim:

Geocoder geocoder = new Geocoder(context);

List<Address> resultados = geocoder.getFromLocationName(endereco, 1);

while (resultados.size() == 0) {
    resultados = geocoder.getFromLocationName(endereco, 1);
}

if(!resultados.isEmpty()){
    LatLng posicao = new LatLng(resultados.get(0).getLatitude(), resultados.get(0).getLongitude());

return posicao;

Aguardo seu retorno.

Oi Bruno.

Não deu certo olha:

private LatLng pegaCoordenadaDoEndereco(String endereco) {

        try {
            Geocoder geocoder = new Geocoder(context);

            List<Address> resultados = geocoder.getFromLocationName(endereco, 1);

            while (resultados.size() == 0) {
                resultados = geocoder.getFromLocationName(endereco, 1);
            }

            if (!resultados.isEmpty()) {
                LatLng posicao = new LatLng(resultados.get(0).getLatitude(), resultados.get(0).getLongitude());

                Log.i("teste", "retornando posição");
                return posicao;
            }
        }catch(IOException e){
            e.printStackTrace();
        }
        Log.i("teste", "retornando null");
return null;
}

StackTrace:

10-14 15:27:27.747 3350-3350/br.com.tcc.searchdrink I/teste: retornando null

Eu já havia tentado fazer isso, parece ser uma chamada assíncrona, não esperarando o while para continuar

Puts cara, achei que resolveria. E se você tentar trazer o log do if() pra primeira linha dele e mudar a condição do if para:

if (resultados.size() > 0)

Mais pra desencargo mesmo...

Da no mesmo amigo, ele nao da print no log pq nem entra. No caso do while, to com um log la dentro que nem imprime, entao creio que seja assíncrono mesmo, ele esta atropelando.

Pqp! Printa o size da variável resultados logo depois que ela é atribuída, vamos ver o que traz.

Da exception, pq resultados fica como null

Tem certeza que a string "endereco" está indo preenchida? Li que em muitos casos esse método retorna null. Tenta colocar na condição daquele while enquanto for nula a a lista:

while(resultados == null)

Está sim. Amigo do nada aqui voltou a rodar normalmente, é um bug que não conheço, esse método retorna null mesmo, mas preciso alterar para não ocorrer na hora da apresentação rs

solução!

Do jeito que está não dá pra deixar, você não pode correr esse risco. Pelo que li, esse método retorna null direto mesmo. Eu de você confirmava com log() se o endereço está vindo certinho e deixava rodando o método dentro do while (resultados == null) até retornar algo, só pra ver se em algum momento retorna mesmo, ou se há mais problemas no seu código.

Oi Lucas, chegou à alguma conclusão?

Oi Bruno, valeu pelas dicas, mas do nada voltou a funcionar, deve ser um bug na API do Google ou falha na resposta do servidor deles.

Bem estranho mesmo.

Tem uma discussão em uma pergunta do StackOverflow (http://stackoverflow.com/questions/4567216/geocoder-getfromlocationname-returns-only-null) em que um cara tenta fazer algo parecido com o que você fez e não funciona, porém depois ele força o fechamento do Maps e reabre novamente, aí funciona. Outro comenta que não estava funcionando no Android 2.2, mas funcionava no 2.0.