Olá povo,
A API do Google Maps disponível para Android é muito bacana, e incorporar esse recurso na sua aplicação pode ser um bom atrativo. Em um dos projetos que trabalhei, precisava mostrar a rota entre dois pontos no mapa, e a Google disponibilizou em 27/07/12 uma API Web que retorna a rota entre duas coordenadas geográficas no formato JSON (ou XML se preferir).
Nesse arquivo, temos uma lista com as coordenadas geográficas que devem ser percorridas desde o ponto de partida até o destino. Com essas coordenadas lidas do JSON, criamos uma lista de LatLng que devem ser desenhadas no objeto GoogleMap através de uma PolyLine.
Não vou detalhar muito a configuração do Google Maps v2 no Android pois já falei nesse post aqui. Também não vou entrar em detalhes sobre leitura de JSON pois falei nesse post aqui. E se você tiver dúvidas sobre AsyncTask, dê uma olhada nesse post.
Vou começar pelo código da Activity mostrado abaixo. No onCreate pegamos a instância de GoogleMap e definimos a posição inicial no mapa e um zoom padrão. Em seguida iniciamos a AsyncTask passando a GoogleMap no construtor e informando a latitude e longitude de origem e destino.
public class TesteRotaMapaActivity extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); SupportMapFragment fragment = (SupportMapFragment) getSupportFragmentManager() .findFragmentById(R.id.map); GoogleMap map = fragment.getMap(); LatLng latLng = new LatLng(-8.102739,-34.89917); map.animateCamera( CameraUpdateFactory.newLatLngZoom(latLng, 12.0f)); new RotaAsyncTask(this, map).execute( // Latitude, Logintude de Origem latLng.latitude, latLng.longitude, // Latitude, Longitude de Destino -23.604262,-46.676513); } }
A classe RotaAsyncTask é quem faz o trabalho de acessar o site do Google Maps, baixar o JSON com a informação da rota.
public class RotaAsyncTask extends AsyncTask<Double, Void, Void>{ private ProgressDialog dialog; private GoogleMap mapView; private Context context; private Route rota; public RotaAsyncTask(Context ctx, GoogleMap mapa) { mapView = mapa; context = ctx; } @Override protected void onPreExecute() { super.onPreExecute(); dialog = ProgressDialog.show( mapView.getContext(), "Aguarde", "Calculando rota"); } @Override protected Void doInBackground(Double... params) { rota = directions( new LatLng(params[0], params[1]), new LatLng(params[2], params[3])); return null; } @Override protected void onPostExecute(Void result) { super.onPostExecute(result); PolylineOptions options = new PolylineOptions() .width(5) .color(Color.RED) .visible(true); for (LatLng latlng : rota.getPoints()) { options.add(latlng); } mapView.addPolyline(options); dialog.dismiss(); } private Route directions( final LatLng start, final LatLng dest) { // Formatando a URL com a latitude e longitude // de origem e destino. String urlRota = String.format(Locale.US, "http://maps.googleapis.com/maps/api/"+ "directions/json?origin=%f,%f&"+ "destination=%f,%f&" + "sensor=true&mode=driving", start.latitude, start.longitude, dest.latitude, dest.longitude); GoogleParser parser; parser = new GoogleParser(urlRota); return parser.parse(); } }
Quem viu o post anterior pode notar que houveram algumas modificações. Delegamos o parse do JSON para a classe GoogleParser e exibimos as rotas utilizando a classe PoluLineOptions (da API v2) com ajuda da classe Route. Essas novas classes foram extraídas desse post aqui. Graças ao comentário do Hadson Gomes.
Eu peguei essas classes e deixei apenas o necessário. Vejamos elas abaixo.
public class Route { private final List<LatLng> points; private String polyline; public Route() { points = new ArrayList<LatLng>(); } public void addPoints(final List<LatLng> points) { this.points.addAll(points); } public List<LatLng> getPoints() { return points; } public void setPolyline(String polyline) { this.polyline = polyline; } public String getPolyline() { return polyline; } }Note que a classe acima tem uma propriedade chamada polyline. Nesse JSON, a rota retorna algumas coordenadas "macro" digamos assim. Por isso os comentários abaixo informando que eram traçadas linhas retas no caminho. A rota com as coordenadas mas precisas estão codificadas em base64 no atributo polyline. A classe GoogleParser faz essa conversão de base64 para GeoPoint conforme abaixo.
public class GoogleParser { protected URL feedUrl; public GoogleParser(String feedUrl) { try { this.feedUrl = new URL(feedUrl); } catch (MalformedURLException e) { } } public Route parse() { // Cria uma rota vazia final Route route = new Route(); try { // Obtém a String do JSON final String result = convertStreamToString( feedUrl.openConnection() .getInputStream()); // Transforma a string em JSON JSONObject json = new JSONObject(result); // Pega a primeira rota retornada JSONObject jsonRoute = json.getJSONArray("routes") .getJSONObject(0); JSONObject leg = jsonRoute .getJSONArray("legs").getJSONObject(0); // Obtém os passos do caminho JSONArray steps = leg.getJSONArray("steps"); final int numSteps = steps.length(); /* * Itera através dos passos, decodificando * a polyline e adicionando à rota. */ JSONObject step; for (int i = 0; i < numSteps; i++) { // Obtém o passo corrente step = steps.getJSONObject(i); // Decodifica a polyline e adiciona à rota route.addPoints( decodePolyLine( step.getJSONObject("polyline") .getString("points"))); } } catch (Exception e) { } return route; } private String convertStreamToString( final InputStream input) { final BufferedReader reader = new BufferedReader( new InputStreamReader(input)); final StringBuilder sBuf = new StringBuilder(); String line = null; try { while ((line = reader.readLine()) != null) { sBuf.append(line); } } catch (IOException e) { } finally { try { input.close(); } catch (IOException e) { } } return sBuf.toString(); } private List<LatLng> decodePolyLine(final String poly) { int len = poly.length(); int index = 0; List<LatLng> decoded = new ArrayList<LatLng>(); int lat = 0; int lng = 0; while (index < len) { int b; int shift = 0; int result = 0; do { b = poly.charAt(index++) - 63; result |= (b & 0x1f) << shift; shift += 5; } while (b >= 0x20); int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1)); lat += dlat; shift = 0; result = 0; do { b = poly.charAt(index++) - 63; result |= (b & 0x1f) << shift; shift += 5; } while (b >= 0x20); int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1)); lng += dlng; decoded.add( new LatLng( (float)(lat / 1E5), (float)(lng / 1E5))); } return decoded; } }Quem viu o post anterior deve lembrar que a classe RouteOverlay não existe mais. Quem faz seu papel é a classe PolyLine da nova versão da Google Maps Api.
A imagem abaixo mostra nossa aplicação em execução.
Qualquer dúvida, deixem seus comentários.
4br4ç05,
nglauber
Ola, gostava de saber se este código esta mesmo funcionando. Se o resultado final é o da figura.. cumprimentos
ResponderExcluirCaramba que orgulho estar "falando" com o próprio Android :)
ResponderExcluirEstá funcionando sim, e como está descrito no postl, a imagem mostra a aplicação em execução.
4br4ç05,
nglauber
Ola, desculpa chamo-me duarte.
ResponderExcluirContudo eu testei esse mesmo código e não esta funcionando. É possível enviar o cofigo fonte, ou é pedir mt..
cumprimentos
Oi Duarte,
ResponderExcluirDesculpa eu. Como o blog tem uma abordagem descontraída, brinquei com o nome que aparece no seu perfil.
Mas bem, o código de exemplo está disponível nesse link: https://sites.google.com/site/nglaubervasc/TesteRotaMapa.zip
Enjoy!
4br4ç05,
nglauber
Nelson,
ResponderExcluirNessa parte aqui do código: String urlRota = String.format(Locale.US,...
da classe RotaAsyncTask.java saiu errado está aparecendo os "&" que não tem no código.
[]´s
Fernando Anselmo
Oi Fernando Anselmo,
ResponderExcluirObrigado pelo aviso. Acabei de corrigir.
4br4ç05,
nglauber
Glauber, parabéns pelo post! Ainda vou testar as dicas mas já vi que tá bem explicado. Me tira só uma dúvida: com essa rota traçada, é possível eu calcular/traçar uma segunda rota entre um #ponto_1 e um #ponto_2, de modo que esse #ponto_2 intersecte a primeira rota traçada? Espero que tenha entendido. xD Qual a melhor forma de fazer isso que estou querendo? Obrigado.
ResponderExcluirOi Thiago,
ResponderExcluirNão sei se entendi sua dúvida. Mas vamos lá.
Nesse exemplo, se você colocar duas coordenadas muito distantes uma da outra, o arquivo XML só retornará parte do caminho.
O que deve ser feito é pegar a última longitude/latitude retornada e traçar a rota desse ponto até o final.
Esse processo deve ser repetido até que se chegue ao ponto desejado.
4br4ç05,
nglauber
Vou tentar simplificar: dado uma rota qualquer (ex: Recife-Caruaru) tem como eu pegar um ponto qualquer do mapa e saber se esse ponto intersecta a rota Recife-Caruaru?
ResponderExcluirOi Thiago,
ResponderExcluirNesse caso, você pode usar a classe android.location.Geocoder que tem um método getFromLocationName que você passa o nome do local e ele retorna uma List<Address>. Nesse objeto Address você pode pegar a latitude e longitude e passar para o método acima.
A classe (Geocoder) normalmente dá problema no emulador (Out of service), mas no aparelho funciona blz.
4br4ç05,
nglauber
Valeu Glauber, talvez isso me ajude. Vou tentar depois. abraço
ResponderExcluirValeu cara o exemplo me ajudou bastante. Dei uma olhada na API e fiquei com duvida sobre como configurar a rota para ela ser gerada especificando os modos de transporte. A pé, carro, ônibus. Valeu!
ResponderExcluirMuito obrigado mesmo! EXCELENTE POST!
ResponderExcluirParabens!
Boas, sou português, e estou a testar seu programa, mas não consigo, registar rotas aqui para portugal, queria perguntar porquê?
ResponderExcluirOi Marcio,
ResponderExcluirEra pra funcionar, afinal estou usando longitude e latitude (que é universal)... Qual o problema que está acontecendo?
4br4ç05,
nglauber
olá,
ResponderExcluirobrigado desde já pela atenção, é o seguinte, queria as rotas daqui em portugal, foi ao google tirar coordenas de dois pontos e depois queria a rota entre estes dois pontos e fiz o seguinte:
new AsyncTask_rotas(mapView).execute(
// Latitude, Logintude de Origem (estação de S. Bento)
-8.608904, 41.145070,
//Latitude, Longitude de Destino (Universidade de Aveiro)
-8.657444, 40.634866);
alterei as coordenadas que tinha por estas, pelo que percebi do seu programa, teria de me aparecer a rota entre estes dois pontos daqui de portugal, mas o que aparece é o mapa dos estados unidos perto do kansas, mas o seu programa funciona, mas com esta alteração que fiz não deu...por isso é que lhe perguntei, só alterei mesmo as coordenadas
cumprimentos
Oi marcio,
ResponderExcluirAcho que você estava colocando os valores invertidos. Testei com esses e funcionou:
// Latitude, Logintude de Origem
40.630142,-8.655639,
// Latitude, Longitude de Destino
41.145586,-8.609934);
4br4ç05,
nglauber
era mesmo isso obrigado
ResponderExcluircumprimentos
olá,
ResponderExcluirnão sei se me pode ajudar, num problema que estou aqui, queria fazer uma bússola que aponta para um geopoint no map, em vez de aponta para o norte magnético, mas não tenho ideia como fazer isso, pensei em adaptar a bussola que aponta para o norte magnético, mas parece me que não será fácil de ser feito, pode até nem ser uma bússola se for uma seta apontar para o geopoint já seria bom e depois atualizava consoante a minha posição
Olá marcio7,
ResponderExcluirVê só... o que você pode tentar é o seguinte: você tem 2 coordenadas C1 e C2. Onde C1 é a posição onde o mapa está exibido e C2 a posição para onde você quer que a bússola aponte.
Dadas essas coordenadas, você pode obter um objeto Projection (mapView.getProjection()) e obter as posições X e Y de C1 e C2 com o método toPixels(GeoPoint).
Depois, você usa as posições x1, y1, x2 e y2 para calcular o ângulo:
a = arctn ((x2-x1) / (y2-y1))
Com isso é só mandar rotacionar a imagem com o ângulo calculado.
Se tiver sucesso posta aqui.
Referência:
http://code.google.com/intl/pt-BR/android/add-ons/google-apis/reference/com/google/android/maps/Projection.html
4br4ç05,
nglauber
ok, obrigado irei testar...sim se conseguir postarei aqui...mais uma vez obrigado, estou a iniciar android, ainda sou novato
ResponderExcluircumprimentos
Nelson, estou procurando por uma solução para o problema: Como mudar uma rota definida? (Ex.: A rota traçada, aí clico num determinado ponto e arrasto até onde pretendo que a rota passe). Isso é possível?
ResponderExcluirObrigado desde já, e parabéns pelo seu blog.
Oi Herivelton,
ResponderExcluirSe eu entendi bem, você tem os ponto A e B. E quando clicar em um local no mapa, mostre o trajeto A->X->B.
O que você pode fazer é chamar o método acima passando A e X; e depois X e B.
Note que no método usamos GeoPoint e você irá clicar no mapa e obter um Point (x e y da tela). Para converter X e Y em latitude/longitude use a classe Projection do MapView (vide comentário anterior para marcio7).
4br4ç05,
nglauber
ótimo post.. se todos fossem assim estaríamos muito melhor...
ResponderExcluirsó uma questão que não consegui resolver: apagar a rota... é que eu crio uma rota, mas existem vários pontos na minha aplicação, e gostaria de apagar a rota para poder criar outra... nesse exemplo eu crio uma em cima da outra... tem como fazer isso??? desde já agradeço e parabenizo...
Oi Cassiano,
ResponderExcluirA rota é traçada em um overlay (um camada) por sobre o mapa. Para remover, basta chamar mapView.getOverlays().clear().
4br4ç05,
nglauber
boa tarde, estou quase a conseguir fazer a bússola só estou com problemas em converter geopoint em location, está em baixo o location é uma classe que está declarada com private nomeclass location;, a localização desta class é do tipo geopoint, mas preciso de converter para Location, tenho o método getLocation(), na classe que designei nomeclass e para fazer essa conversão, fiz o seguinte código embaixo, espero que me possa ajudar já tentei de várias maneiras, mas nada como sou novato nisto tenho algumas dificuldades, como combinado depois colocarei aqui a bussola feita apontar para um ponto de interesse, só não lhe enviei pk não a consegui colocar a funcionar
ResponderExcluircumprimentos
marcio7
double latitude = location.getLocation().getLatitudeE6() / 1E6;
double longitude = location.getLocation().getLongitudeE6() / 1E6;
Location local = null;
local.setLatitude(latitude);
local.setLongitude(longitude);
Olá marcio7,
ResponderExcluirPara fazer a conversão de GeoPoint para Pixels, você pode usar a o método toPixels da classe Projection
Projection proj = mapView.getProjection();
Point ponto = proj.toPixels(geoPoint, null);
4br4ç05,
nglauber
olá, boa tarde, obrigado pela resposta,
ResponderExcluirno meu caso não poderá ser conversão de geopoint em point mas sim conversão de GeoPoint em Location, porque preciso de usar um método em que o argumento que passo tem do tipo Location e não do tipo GeoPoint
float bearing = currentLocation.bearingTo(local);
o currentLocation é minha localizaão do tipo Location
conversão que tento fazer mas dá null
double latitude = location.getLocation().getLatitudeE6() / 1E6;
double longitude = location.getLocation().getLongitudeE6() / 1E6;
Location local = null;
local.setLatitude(latitude);
local.setLongitude(longitude);
location é do tipo Geopoint e preciso de passar a tipo Location, e uso a conversão acima, só que dá sempre null o getLocation()é um método que está noutra classe que devolve GeoPoint location
há algo aqui que me está a escapar, mas n sei o que é, já tentei de várias maneiras e nada
muito obrigado pela disponibilidade
cumprimentos
Márcio Fernandes
olá, bom dia, já resolvi o problema, obrigado pela disponibilidade, agora estou a ver um pequeno pormenor, depois disponibilizarei o código que fiz para a bussola
ResponderExcluirem relação ás rotas no mapa, agora estava a pensar colocar o ponto de origem a minha localização atual e na destino o ponto que estou interessado, é possível fazer isso, sem ser com os valores de teste?
cumprimentos
marcio7
Oi marcio7,
ResponderExcluirAcho que isso aqui vai te ajudar:
http://nglauber.blogspot.com.br/2011/10/google-maps-e-gps.html
4br4ç05,
nglauber
olá,boa tarde
ResponderExcluirobrigado, ajudou até apliquei na bússola, ainda n consegui desenhar a seta, porque á uma lado que me aparece a null a localização, mas deve ser algo pequeno, parece me que estou perto...
cumprimentos
marcio7
Opa, tudo bem Nelson?
ResponderExcluirPrimeiramente parabéns pelo post, ta bem explicado. Estou tentando testa-lo e estou pegando o seguinte erro:
"
Description Resource Path Location Type
The method getTextContent() is undefined for the type Node RotaAsyncTask.java /TesteRotaMapaActivity/src/ngvl/android/rota line 83 Java Problem "
O erro esta na seguinte linha de código:
String coordenadasStr = coordenadasXML.getTextContent();
Procurei na internet como resolver esse erro mas não tive muito sucesso. Sabo o que pode estar acontecendo?
Agradesço desde ja pela atenção.
Bruno Henrique de Souza
Oi Bruno,
ResponderExcluirO problema é que usei a API 2.3 do Android. Nas versões anteriores, você deve usar getFirstChild().getNodeValue() ao invés do getTextContent().
4br4ç05,
nglauber
PS.: Esse problema já tinha sido descrito aqui :)
http://nglauber.blogspot.com.br/2011/11/lendo-rss-no-android.html
olá boa tarde, coloquei a bússola em funcionamento, com valores de teste, como quer que lhe envie o código?
ResponderExcluircomo estava combinado, desde já agradeço a sua disponibilidade para me ajudar
cumprimentos
marcio7
Oi marcio7,
ResponderExcluirQue bom que concluiu o projeto. Se quiser, pode mandar pro meu email.
4br4ç05,
nglauber
Muito bom!
ResponderExcluirÓtima iniciativa, funciona muito bem, fácil entendimento.
Obrigado por compartilhar.
Muito bom
ResponderExcluirE ae, beleza?
ResponderExcluirCara, muito obrigado pelo tutorial.
Estou com uma duvida, criei um projeto que traça a rota entre eu o um ponto que clicar no mapa... o problema aparece que eu não consigo apagar do mapa a rota se ele clicar em outro ponto, entendeu?
Então o mapa vai ficando cheio de rotas traçadas..
Alguém pode me ajudar?
Oi Ricardo,
ResponderExcluirPra fazer isso, é só remover o overlay anterior ao clicar no mapa.
mapView.getOverlays().clear()
4br4ç05,
nglauber
Entao cara, esqueci de dizer q quando faço isso a minha localização e os outros overlays do mapa somem... eu usei a api do google place para aparecer os outros lugares (overlays).... desde ja agradeço sua ajuda... mas como posso resolver esse problema? Pode por favor me ajudar a eliminar a rota quando clico em outro overlay?
ResponderExcluirOi Ricardo,
ResponderExcluirBem, o que você pode fazer é armazenar em uma variável temporária (do tipo GeoPoint) o seu local atual. Aí quando você clicar em um outro do mapa você traça a rota do seu local atual (que está na variável temporária) até o local onde você clicou.
4br4ç05,
nglauber
opa nao sei c reparou pq em rotas grandes por ex. de porto alegre a sp
ResponderExcluirele traça apenas um pedaço..nao chega a completar ela tipow ele traça 20%
Oi José Carlos,
ResponderExcluirPercebi sim. Inclusive pensava que tinha colocado no post. Isso é uma limitação da API do Google Maps. O que você deve fazer é tentar pegar a última coordenada do arquivo XML e fazer a busca do XML novamente a partir desse local até o local de destino, e repetir isso até que a localização seja encontrada.
4br4ç05,
nglauber
Grande Nelson, muito obrigado pelo post!
ResponderExcluirMas estou com um probleminha, estou desenvolvendo um aplicativo para o android 2.1, já alterei o código trocando
String coordenadasStr coordenadasXML.getTextContent();
por String coordenadasStr = coordenadasXML.getFirstChild().getNodeValue();
Feito isso, o código para de acusar erro mas após compilar ocorre um erro quando está calculando rota.
Por favor, estou precisando muito rodar no 2.1.
Oi Willams,
ResponderExcluirTenta colocar um log ou coloca um breakpoint e faz o debug pra ver o que essa tag está retornando. Teoricamente ela deve retornar o mesmo conteúdo do getTextContent.
4br4ç05,
nglauber
Nelson,
ResponderExcluirboa tarde.
Primeiro gostaria de parabenizar pelo excelente artigo.
Estou criando uma app que coleta localizações e em seguida deveria mostrar o percurso entre o primeiro e o último ponto. Tentei usar sua solução aqui, mas sem sucesso. O retorno da url é um html cheio de javascript e não localiza a tag LineString dando erro no parse.
Tens alguma idéia se o código ainda está ok, ou o Google mudou o retorno ?
Grato
Ola glauber,
ResponderExcluirEntão, estou debugando e a variável coordenadasStr recebe um valor nulo, ou seja, o getfirstchild() esta retornando nulo.
Oi Glauber,
ResponderExcluirA URL do serviço mudou e o XML também, consequentemente o parser terá que mudar. A nova URL é essa:
http://maps.googleapis.com/maps/api/directions/xml?origin=40.630142,-8.655639&destination=41.145586,-8.609934&sensor=true
Mais informações aqui:
https://developers.google.com/maps/documentation/directions/
Em breve devo estar atualizando o post.
4br4ç05,
nglauber
Oi Willams e Glauber,
ResponderExcluirAcabei de atualizar o POST. Apenas a classe RotaAsyncTask foi impactada. Testem e me dêem um feedback :)
4br4ç05,
nglauber
Oi Glauber, eu nem sou o Willams nem o Glauber, mas vou te responder rsrsrs
ResponderExcluireu também estava usando seu código que funcionava muito bem, mas desde o ultimo sábado 28/07 percebi que a rota não estava mais sendo traçada no mapa, dava uma exceção no parse do xml.
Agora sim, voltou a funcionar, só que no teste inicial que fiz a rota ficou muito "fora" da estrada, como se o intervalo de pontos estivesse muito alto gerando uma rota em "linha reta".
Depois vou tentar entender o porque e vê se dá pra melhorar, se consegui alguma coisa eu aviso
Oi Julio,
ResponderExcluirValeu pelas informações. A URL e a estrutura do XML mudaram. Aí fiz um ajuste bem rápido e para o que eu tinha testado, funcionou. Mas se você tiver uma solução melhor, pode mandar que eu ajusto aqui no post.
4br4ç05,
nglauber
Oi Nelson,
ResponderExcluirMuito bom este seu post.
Eu procurava por uma explicação detalhada como esta a algum tempo.
Valeu!
Meu caro,
ResponderExcluirobrigado pelo retorno.
Fiz os ajustes por aqui e está ok.
O único senão é que alguns pontos coletados pelo GPS ficaram um pouco fora da via e ao traçar a rota o serviço dá uma volta no quarteirão ao lado da via por exemplo, ficando um pouco estranho, mas vou tentar ajustar aqui.
Obrigado e parabéns por compartilhar o conhecimento.
Abraços,
Glauber
Glauber,
ResponderExcluirFui seu aluno na Especializa e estou com algumas dúvidas urgentes e se puder me ajudar agradeço!
Tenho um projeto que é para traçar rota no Mapa!
Tenho um mapa já com pontos de Destinos(Lojas) e quero traçar a rota do meu local atual para a loja que é um overlay no mapa.
Minha dúvida é......
Não consigo pegar as coordenadas da minha posição atual e nem traçar a rota!
Grato,
Oi Marcos,
ResponderExcluirEsse post aqui pode te ajudar, ele mostra como pegar a posição do GPS.
http://nglauber.blogspot.com.br/2011/10/google-maps-e-gps.html
Para pegar a última posição conhecida do GPS, você pode usar esse método aqui.
http://developer.android.com/reference/android/location/LocationManager.html#getProvider(java.lang.String)
4br4ç05,
nglauber
Olá Nelson, estive testando seu código porém tive um pequeno problema, ele gera a rota, porém entre os pontos que ele busca no google, ele traça caminhos retos e não seguindo o mapa, ficando fora da estrada.
ResponderExcluirTem idéia do que possa ser?
Abraços
Oi Jayme,
ResponderExcluirEu não testei intesivamente esse código. Como comentei, a API do Google mudou recentemente, então tive que fazer um ajuste no post.
Mas para você debugar, é só pegar a URL das linhas 25/28 e abrir no browser. O endereço retorna um XML, então você deve fazer o parser dele.
4br4ç05,
nglauber
Obrigado pela atenção Nelson,
ResponderExcluirestou revirando o código até agora e ainda não tive sucesso.
Verifiquei como indicou, porém o XML vem correto e o parser também faz a leitura da forma correta.
Creio que o problema aqui seja referente a maneira como é traçado o caminho, pois temos 2 pontos originais que depois se transformam em vários pontos, porém quando o android tenta traçar uma linha entre 2 pontos, sera uma reta, não fazendo a logica ao mapa.
Tenho uma dúvida agora, que ainda não entendi, como era feito antes essa linha? Você apenas indicava os 2 pontos e ele traçava uma linha que se adaptava às ruas do mapa?
Grato novamente e desculpas por estar tomando seu tempo.
36Olá, meu nome é Fillipe e estou enfrentando o mesmo problema com o desenho da rota. Por algum motivo não está ficando nas ruas, vcs já conseguiram resolver esse problema?
ResponderExcluirParabéns seu post está ótimo
Olá Nelson, apenas estou passando aqui para mostrar a solução que acabei de encontrar para o meu problema. No caso ali, acho que o problema esta referente a decodificação dos pontos para exibir no mapa, com o código que é mostrado aqui:
ResponderExcluirhttp://stackoverflow.com/questions/11323500/google-maps-api-version-difference/11357351#11357351
É possível conseguir o mesmo resultado.
Depois verei como fazer para continuar utilizando o XML.
Obrigado
Bom dia , gostaria se o código acima resolveu o problema de seguir as ruas corretamente ?
ResponderExcluirBoa tarde , estou tentando fazer uma rota baseado no seu código , mais aconteceu o mesmo erro das pessoas acima, a rota que ele traca fica fora das ruas , eu vi que o Jayme postou um link , tentei fazer como ensina esse link mais não consegui , sera que alguem pode me dar uma ajudinha ?
ResponderExcluirBoa noite pessoal, achei esse blog na net ha alguns dias, implementei esse codigo e tb obtive o mesmo erro que o pessoal tem relatado, entao a partir desse codigo comecei a efetuar outras soluçoes e encontrei :).
ResponderExcluirAgora estou a melhorá-lo. Agradecido desde já
Segue Link
http://stackoverflow.com/questions/11745314/why-retrieving-google-directions-for-android-using-kml-data-is-not-working-anymo/11745316#11745316
Oi Hadson,
ResponderExcluirValeu pela contribuição. A solução que você indicou funciona bem. Quando a distância é longa, ainda fica lento, mas a gente vai aprimorando.
4br4ç05,
nglauber
Mt bom meu velho!!!
ResponderExcluirE valeu pela referência do meu post sobre o AsyncTask =)
Pra refrescar a memória sou eu wolverine ;)
Ola, primeiramente parabéns pelo post.
ResponderExcluirestou com uma dúvida, como faço para traçar uma rota a partir do meu ponto de oriigem, tenho que capturar a minha longitude e latidude atual, e traçar a rota até uma String, sendo que tenho que converter a String para latidude e longitude tbm, se possivel gostaria que me desse opções de rota, por ser uma String o desdino.
oi joaohsenger,
ResponderExcluirDá uma olhada nesse post:
http://nglauber.blogspot.com.br/2011/10/google-maps-e-gps.html
4br4ç05,
nglauber
Otimo post cara , eu tinha olhado o post antigo e rota ficou fora das ruas devido a mudança da API , dai tambem segui esse post e consegui , minha duvida agora é como traçar a rota mais rapida ? eu consigo por muitos pontos e fazer muitas rota , mais como definir a mais rapida ?
ResponderExcluirOlá! Muito bom seu post! Estou tentando executar o seu código fonte diretamente do meu celular (Xperia NEO V), ele traça a rota porém o mapa não é exibido. Por favor, pode me dizer o que pode ser? Estou com o 3G ligado e no meu manifest eu inclui a lib com.google.android.maps. Obrigado!
ResponderExcluirOi Anônimo,
ResponderExcluirO problema provavelmente é a permissão de INTERNET ou a chave do Google Maps que está errada. Note que essa chave é por arquivo debug.keystore.
Testa isso aqui: http://nglauber.blogspot.com.br/2009/09/google-maps-com-android-15.html
4br4ç05,
nglauber
Olá Nelson!
ResponderExcluirAinda estou com problemas na exibição do mapa.
Rodei sua aplicação no emulador e no celular e em ambos o mapa não aparece =/
Eu coloquei a versão do aplicativo pra google api pois na versão que estava dava erro.
Será que está faltando alguma coisa? Vc importou o jar do maps?
Obrigado!
Olá Glauber! Resolvi o problema do mapa. Por algum motivo a key que gerei anteriormente ficou inválida e o google não estava aceitando. Gerei uma nova e deu certo! []'s e parabéns pelo blog! Me ajudou muito!
ResponderExcluirPessoal, alguém saberia me dizer, ou me passar algum link, onde tenha algum exemplo de como desenhar uma polyline de um ponto ao outro na API do Google Maps para Android? ja pesquisei mas eu só acho isso em javascript, para aquelas aplicações que rodam nos navegadores, não estou conseguindo encontrar algum exemplo pronto para a API do Android em que eu possa me basear. Eu consegui rodar o exemplo do site, mas no momento eu não preciso calcular a Rota, só fazer o desenho como se fosse um "Grafo" de determinado bairro. Muito Obrigado!
ResponderExcluirParabens pela aplicaçao, gostaria de saber se vc tem ela para download ?
ResponderExcluirPessoal, eu consegui fazer o desenho das rotas funcionar, mas meu mapa esta estranho, ele não carrega corretamente, fica aparecendo alguns quadrados com um x no meio, partes carregam normal, e outras ficam com esse quadrado. O que poderia ser?
ResponderExcluirOlá Anônimo,
ResponderExcluirIsso acontece normalmente quando vc dá um zoom muito grande em uma determinada área. Nem todos os locais suportam o zoom máximo.
4br4ç05,
nglauber
Muito Obrigado Nelson, eu consegui arrumar de uma maneira diferente o problemas do x que estava aparecendo em alguns lugares em vez do mapa, eu passei minha aplicação para a versão do google maps API 2.3.3 e o problema sumiu, meio, estranho isso, mas ja esta funcionando normalmente. Valeu!
ResponderExcluirOlá, pelo código, a marcação de rota respeita o sentido das ruas, pois está como rota pra carro, e se quiser habilitar uma rota pra pedestre? como faço??
ResponderExcluirOlá Henrique,
ResponderExcluirVocê pode acessar a documentação completa aqui:
https://developers.google.com/maps/documentation/directions/?hl=pt-br
Para pegar a rota a pé, você pode passar o parâmetro mode=walking na URL.
4br4ç05,
nglauber
Olá de novo, li a documentação, tao simples né, rsrsrsrs, ótimo blog, continue assim ajudando iniciantes, rsrsrs, outra duvida, que venho batendo cabeca a mt tempo: tenho 1 ponto marcado no mapa, e gostaria de clicar nele e abrir um dialog, algo em que descreva aquele mapa, usando um xml! vc saberia? abraços!
ResponderExcluirOI Henrique,
ResponderExcluirEsse tutorial acho que faz o q você quer:
https://developers.google.com/maps/documentation/android/hello-mapview
O método onTap do OverlayItem faz isso.
4br4ç05,
nglauber
Bom dia novamente, no meu mapa tem a minha localização(GPS) e varios pontos marcados no mapa, quando eu clico nesses pontos marcados no mapa, o metodo onTap() é executado, abrindo um Dialog na tela com um botao Marcar Rota até o ponto escolhido, mas está dando um erro, e já estou ficando maluco, kkkkkkk, me ajudem!
ResponderExcluirAló Glauber, muitoooo obrigado por esse post. Mim ajudou muito =D.
ResponderExcluirO exemplo pra download está diferente do código do post. Muito obrigado.
Oi Diogo,
ResponderExcluirNão tem de que. Estamos aqui pra ajudar. Ah! Acabei de atualizar o post.
4br4ç05,
nglauber
Olá, em relação as rotas, gostaria de saber se é possível criar a própria rota, e não o caminho que o Google mostra, tipo.. eu gravar o caminho que é pra aparecer do inicio ao destino.. como por exemplo dentro de uma cidade, ponto inicial minha casa e ponto final uma loja.
ResponderExcluirOi Fausto,
ResponderExcluirNão sei se entendi a pergunta, mas você pode fazer a pesquisa pelos locais de origem e destino usando a classe GeoCoder.
http://developer.android.com/reference/android/location/Geocoder.html
Ela permite você fazer uma busca pelo nome do local e te retorna a latitude e a longitude.
Daí é só usar o código desse post.
4br4ç05,
nglauber
Olá..Pessoal. Estava estudando o código disponibilizado e estou encontrando um problema pois não consigo fazer um conversão de LatLng para GeoPoint.
ResponderExcluirOlá Fundamentos de Programação,
ResponderExcluirBasta multiplicar a latitude e longitude do objeto LatLng por 1E6 e passar para o construtor da classe GeoPoint.
4br4ç05,
nglauber
Olá. Estou com um problema, no trecho a seguir estou recebendo a mensagem de Type mismatch: cannot convert from element type GeoPoint to LatLng
ResponderExcluirfor (LatLng latlng : rota.getPoints()) {
options.add(latlng);
}
Alguma sugestão do que posso fazer?
Oi Lucas,
ResponderExcluirAgora que vi que a classe Route estava retornando uma List ao invés de uma List.
Post corrigido.
4br4ç05,
nglauber
Ola Gostaria de saber como faço pra transformar as coordenadas em nome de rua e vice versa?
ResponderExcluirOi Renan,
ResponderExcluirO pessoal já perguntou isso nos comentários acima. Dá uma procurada em GeoCoder. Essa classe realiza essa tarefa.
4br4ç05,
nglauber
Gostaria de saber como é o funcionamento da classe SupportMapFragment ?
ResponderExcluirOi Anônimo,
ResponderExcluirO SupportMapFragment serve para podermos utilizar o Fragment de Mapas em versões anteriores a 3.0 (API Level 11). Mais informações você pode obter na documentação da classe.
http://developer.android.com/reference/com/google/android/gms/maps/SupportMapFragment.html
4br4ç05,
nglauber
Opa, estou com problema no Geopoint da class RotaAsync, ele recebe um objeto do tipo LatLng e não reconhece como faço pra converter esse objeto pra Geopoint ou se tem como criar direto como LatLng?
ResponderExcluirOi Anônimo,
ResponderExcluirAcabei de corrigir o post. Dá uma olhada.
4br4ç05,
nglauber
Oi nelson.....se no lugar dessa Latitude de origem eu quizer colocar a localização do meu gps(celular), como eu faço para pegar essa localização e traçar a rota...
ResponderExcluirabç!!
Oi Zeca,
ResponderExcluirVocê pode usar o método getLastKnownLocation da classe LocationManager: http://developer.android.com/reference/android/location/LocationManager.html#getLastKnownLocation(java.lang.String)
Qualquer dúvida, dá uma olhada aqui:
http://nglauber.blogspot.com.br/2011/10/google-maps-e-gps.html
4br4ç05,
nglauber
Boa Tarde Glauber
ResponderExcluirGostaria de saber se esse projeto https://sites.google.com/site/nglaubervasc/TesteRotaMapa.zip - funciona com api v2,
Pois estou enfrentando problemas com a rota.. implementei tudo certo,aparece o mapa e a rota, mais a aplicação fecha inesperadamente, não permanece on, diferente desde projeto TesteRotaMapa.zip que fica "ligado' e podemos navegar no mapa a vontade, gostaria de uma ajuda sua, pois necessito no meu projeto que seja traçada a rota e a aplicação permaneça on, pleace...pleace..
Oi Anônimo,
ResponderExcluirQual erro está acontecendo? Dá uma olhada no logcat.
4br4ç05,
nglauber
Boa Tarde Glauber sou o antônio, que anteriormente postei um comentário como anônimo, errei na hora de colocar meu nome....
ResponderExcluirA aplicação aparentemente não tem erro de compilação, mais ele fecha inesperadamente, a mensagem que da no logcat é a seguinte...
10-04 16:28:23.250: E/Trace(1031): error opening trace file: No such file or directory (2)
10-04 16:28:25.980: W/GooglePlayServicesUtil(1031): Google Play Store is missing.
10-04 16:28:25.999: W/GooglePlayServicesUtil(1031): Google Play Store is missing.
10-04 16:28:26.009: W/GooglePlayServicesUtil(1031): Google Play Store is missing.
10-04 16:28:26.029: W/GooglePlayServicesUtil(1031): Google Play Store is missing.
10-04 16:28:26.039: W/GooglePlayServicesUtil(1031): Google Play Store is missing.
10-04 16:28:26.159: W/GooglePlayServicesUtil(1031): Google Play Store is missing.
10-04 16:28:26.170: D/AndroidRuntime(1031): Shutting down VM
10-04 16:28:26.170: W/dalvikvm(1031): threadid=1: thread exiting with uncaught exception (group=0x40a71930)
10-04 16:28:26.269: E/AndroidRuntime(1031): FATAL EXCEPTION: main
10-04 16:28:26.269: E/AndroidRuntime(1031): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.testemapas/com.example.testemapas.MainActivity}: java.lang.NullPointerException: CameraUpdateFactory is not initialized
10-04 16:28:26.269: E/AndroidRuntime(1031): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)
10-04 16:28:26.269: E/AndroidRuntime(1031): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
10-04 16:28:26.269: E/AndroidRuntime(1031): at android.app.ActivityThread.access$600(ActivityThread.java:141)
10-04 16:28:26.269: E/AndroidRuntime(1031): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
10-04 16:28:26.269: E/AndroidRuntime(1031): at android.os.Handler.dispatchMessage(Handler.java:99)
10-04 16:28:26.269: E/AndroidRuntime(1031): at android.os.Looper.loop(Looper.java:137)
10-04 16:28:26.269: E/AndroidRuntime(1031): at android.app.ActivityThread.main(ActivityThread.java:5041)
10-04 16:28:26.269: E/AndroidRuntime(1031): at java.lang.reflect.Method.invokeNative(Native Method)
10-04 16:28:26.269: E/AndroidRuntime(1031): at java.lang.reflect.Method.invoke(Method.java:511)
10-04 16:28:26.269: E/AndroidRuntime(1031): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
10-04 16:28:26.269: E/AndroidRuntime(1031): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
10-04 16:28:26.269: E/AndroidRuntime(1031): at dalvik.system.NativeStart.main(Native Method)
10-04 16:28:26.269: E/AndroidRuntime(1031): Caused by: java.lang.NullPointerException: CameraUpdateFactory is not initialized
10-04 16:28:26.269: E/AndroidRuntime(1031): at com.google.android.gms.internal.ac.a(Unknown Source)
10-04 16:28:26.269: E/AndroidRuntime(1031): at com.google.android.gms.maps.CameraUpdateFactory.aV(Unknown Source)
10-04 16:28:26.269: E/AndroidRuntime(1031): at com.google.android.gms.maps.CameraUpdateFactory.newLatLngZoom(Unknown Source)
10-04 16:28:26.269: E/AndroidRuntime(1031): at com.example.testemapas.MainActivity.onCreate(MainActivity.java:23)
10-04 16:28:26.269: E/AndroidRuntime(1031): at android.app.Activity.performCreate(Activity.java:5104)
10-04 16:28:26.269: E/AndroidRuntime(1031): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
10-04 16:28:26.269: E/AndroidRuntime(1031): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
10-04 16:28:26.269: E/AndroidRuntime(1031): ... 11 more
10-04 16:28:26.399: D/dalvikvm(1031): GC_CONCURRENT freed 233K, 13% free 2588K/2952K, paused 7ms+32ms, total 209ms
Pleace, pleace....preciso muito dessa rota....grato!!!
oi Antônio,
ResponderExcluirPor acaso você está usando o emulador nativo do Android? Se sim, você não vai conseguir rodar mesmo. Isso porque, essa API precisa do Google Play pra funcionar.
Uma sugestão seria você usar o Genymotion (http://www.genymotion.com/).
4br4ç05,
nglauber
Olá Nelson, parabéns pelo Blog e pela interação com as pessoas que curtem o seu trabalho.
ResponderExcluirEstou desenvolvendo um aplicativo que precisa calcular rotas que não tem no Google Maps. Existe uma forma de eu criar essas rotas?
É um aplicativo utilizando Google Maps V2 que da a posição e rota para chegar os prédios de uma faculdade.
No aguardo, obrigado.
Oi Daniel,
ResponderExcluirDepois que escrevi esse post, virei sumidade em traçar rotas com Google Maps :)
Pelo menos é o que o pessoal pensa...
Cara realmente não sei te responder, mas se você tem a Lat/Lng dos dois pontos, a API do Google traça a rota pra você.
4br4ç05,
nglauber
Boa tarde,
ResponderExcluiré possível usar essas rotas do google api sem mostrar o mapa?
eu gostaria de calcular apenas as distâncias de pontos determinados em relação ao meu ponto atual e mostrar um número (ex. 100 metros)
Oi Tedesco,
ResponderExcluirÉ sim... Basta usar apenas o webservice do Google Maps.
4br4ç05,
nglauber
Muito obrigado pelo post. Funcionou perfeitamente aqui.
ResponderExcluirOlá,
ResponderExcluirEstou com um problema. Como faço para abrir um arquivo .kml que já está salvo em uma pasta do aplicativo?
Oi Boa tarde!
ResponderExcluirPrimeiramente parabéns, e obrigado por compartilhar o seu conhecimento conosco.
Sua solução funcionou perfeitamente, muito legal!
Mas eu gostaria de saber se tem como eu obter a distancia em KM entre esses dois pontos da rota?
Abraços
Oi Anderson,
ResponderExcluirQue bom que conseguiu. Para pegar a distância, você pode ler o atributo "distance" do JSON de retorno.
Dá uma olhada nesse link:
https://developers.google.com/maps/documentation/directions/?hl=pt-br#DirectionsResponses
4br4ç05,
nglauber
Ola Nelson , me chamo Breno , bom estou com dificuldade de implementar o Gps no codigo da Rota vc tem alguma sugestão e meu main activity não reconhece geopoint , MapController
ResponderExcluirOi Breno,
ResponderExcluirEssas duas classes que você falou é da antiga API do Google Maps. Recomendo você utilizar a v2.
http://www.nglauber.com.br/2012/12/android-google-maps-v2.html
E quanto a rota, você pode ver nesse outro post aqui:
http://www.nglauber.com.br/2011/10/google-maps-tracando-rotas.html
4br4ç05,
nglauber
Parabéns pelo tutorial. Em exemplo, eu peço um taxi e gostaria de visualizar em tempo real o trajeto que ele está percorrendo até chegar onde estou. Tem como fazer isso? Estou começando agora não tenho muito conhecimento. Tipo eu pensei que teria que ficar atualizando o banco com a localização do motorista e no lado do cliente eu buscaria esses dados e mostraria. Seria isso?
ResponderExcluirObrigado pelo post!
Oi Rodrigo,
ResponderExcluirTem um exemplo com isso no meu livro. Basicamente é uma evolução desse post.
Inclusive fiz uma correção sobre ele, pois a API mudou poucos dias depois que o livro foi impresso.
http://www.nglauber.com.br/2015/01/dominando-o-android-atualizacao-1.html
4br4ç05,
nglauber
bom dia meu caro!
ResponderExcluirbom estou com um pequeno problema, eu baixei o teu codigo, mas ao testar ele nao aparece nada, so a rota determinada, sera que e problema na hora de executar o app?
Oi Anônimo,
ResponderExcluirDeve ser problema com a chave que você cadastra no site.
4br4ç05,
nglauber
Caro Nelson, juntamente com meus amigos do IFMS estamos utilizando do seu código como base de um aplicativo que utiliza google maps, entretanto, encontramos o seguinte erro: O mapa não aparece, mas, apenas a rota sem este.
ResponderExcluirPoderia nos ajudar nisso?
Atenciosamente: Nayara
Bom dia, baixei o teu codigo mas quando executo aparece o seguinte erro...
ResponderExcluirEstilos ausentes. É o tema escolhido para esta correto layout? Use a caixa de combinação do tema acima do layout para escolher um layout diferente , ou corrigir as referências de estilo tema . Não foi possível encontrar estilo ' mapViewStyle ' no tema atual
o problema pode ser falta de atualização do meu compilador?
Oi Reinaldo,
ResponderExcluirEm tempo de projeto não vai aparecer mesmo... Se rodar e funcionar tá tudo bem :)
Qualquer dúvida, dá uma conferida no código do meu livro. Tá disponível no GitHub.
4br4ç05,
nglauber
Olá Nelson, estou tendo um problema com meu app. A rota está funcionando certinho quando coloco para aparecer pela primeira vez, mas quando coloco pela segunda vez em um lugar diferente, é atualizado apenas o marcador mas a rota continua no antigo lugar. Estou seguindo o exemplo de seu livro (que por sinal é ótimo). Abraços.
ResponderExcluirOi Cínthia,
ResponderExcluirEu respondi seu email, mas para registrar aqui também :)
A questão da rota é que você precisa fazer uma nova requisição para a API de Directions com os novos pontos de origem e destino. Essa implementação está nas classes RotaHttp e RotaTask.
Com a lista de LatLng que é retornada pelo método carregarRota(LatLng,LatLng) você atualiza o atributo mRota da MainActivity e chama o método atualizarMapa().
4br4ç05,
nglauber
nglauber pode me disponibilizar o link de seu livro?
ResponderExcluirOi Reinaldo,
ResponderExcluirSegue abaixo.
http://novatec.com.br/livros/dominandoandroid/
Em breve sairá a segunda edição.
4br4ç05,
nglauber
Este comentário foi removido por um administrador do blog.
ResponderExcluirmuito bem explicado, gostei bastante do post!!!
ResponderExcluirParabéns mano.
Olá Glauber,
ResponderExcluirComo eu faço para adicionar waypoints na rota??
Oi Wesley,
ResponderExcluirPelo que eu sei, para cada trajeto você deve fazer uma nova consulta ao webservice.
4br4ç05,
nglauber