Depois que escrevi o post sobre como criar um app Android com GPS muitos leitores me pediram para fazer uma parte 2, contendo um tutorial de como pinnar um local no mapa do Google dentro de um app. Isso é algo extremamente fácil de fazer em plataformas híbridas como Phonegap, mas gera um tanto de dúvidas em apps nativos, motivo do post de hoje.
Veremos neste post:
- Criando e configurando o projeto
- Criando o AVD com suporte a Google APIs
- Exibindo o mapa
- Marcando a posição atual
Criando e configurando o projeto
Primeiro, crie um novo projeto no Android Studio chamado MapApp com qualquer versão de Android acima da 4 e escolha como activity inicial uma do tipo Map Activity, como na imagem abaixo.
Isso irá criar alguns arquivos diferentes no seu projeto. O primeiro deles, google_maps_api.xml, estará na pasta values e será aberto automaticamente quando seu projeto for criado, indicando que você deve, antes de mais nada, obter uma API Key do Google Maps para poder fazer essa integração.
Para obter tal API, acesse esse link e preencha todos os dados que eles pedirem para obter uma chave. Se o link não funcionar é porque está configurado para minha aplicação, mas não se preocupe, esse link está comentado no seu google_maps_api.xml, então é só copiar e colar, como mostra a imagem abaixo:
Depois que inserir a api key onde diz YOUR API KEY HERE, mande rodar o seu app para que veja que ele já funciona, pinnando a localização de Sidney, na Australia. No entanto, é bem provável que seu emulador inicie, mas não rode o app, exibindo alguma mensagem como “your application relies on Google Play Services which is not supported by your device”, isso porque essas integrações com APIs do Google não funcionam em emuladores por padrão. Temos que criar um tipo especial de emulador para que funcione.
Criando o AVD com suporte a Google APIs
Primeiro, você terá de baixar o pacote Google APIs para a versão do Android que pretende emular, como a 5.1.1 na imagem abaixo:
Depois que baixar, você deverá criar um novo AVD, usando a versão “Google APIs” de Android, como mostra a imagem abaixo:
Já a imagem abaixo mostra a criação da mesma máquina, mas no Eclipse:
A primeira vez que executar esse AVD com Google APIs, ele provavelmente irá ficar parado um tempo atualizando com a mensagem “Google Play services are updating”. Aguarde até que termine e possa usá-lo corretamente (se ficar muito tempo travado nessa tela, experimente fechar apenas o Android Studio e abrir de novo, às vezes o ADB se perde).
Atenção: caso não esteja usando o emulador nativo do Android SDK (o que vem no Android Studio), usando ferramentas de terceiros como o Genymotion, por exemplo, não vai funcionar seu app de mapa. Para fazer funcionar nessas plataformas de terceiros, que não vem com o Google Play Services instalado, você vai precisar fazer mais alguns passos.
Exibindo o mapa
Depois que o AVD terminar de atualizar, e estiver plenamente funcionando apenas mande rodar seu app que você verá o mapa funcionando com um pin em Sidney, Australia.
O app está pinnando esta localização por causa desse trecho de código aqui, presente no método onMapReady da classe MapsActivity.java:
1 2 3 4 5 6 7 8 9 10 11 |
@Override public void onMapReady(GoogleMap googleMap) { mMap = googleMap; // Add a marker in Sydney and move the camera LatLng sydney = new LatLng(-34, 151); mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney")); mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney)); } |
Ou seja, caso você fixe a latitude e longitude no construtor da variável sydney, o mapa irá pinnar o local informado, como abaixo, onde pinei -30, -51, próximo a Porto Alegre/RS.
‘Bora fazer ele pinnar sua localização atual?
Marcando a posição atual
Primeiro vamos pegar emprestado alguns códigos de outro tutorial aqui do blog, o Como criar um app Android com GPS, que ensina como pegar a localização atual do dispositivo em coordenadas geográficas (latitude e longitude).
No mesmo método onMapReady, vamos pegar as coordenadas geográficas atuais para instanciar o objeto corretamente, como abaixo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
@Override public void onMapReady(GoogleMap googleMap) { mMap = googleMap; try{ LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); LocationListener locationListener = new LocationListener() { public void onLocationChanged(Location location) { LatLng latlng = new LatLng(location.getLatitude(), location.getLongitude()); mMap.addMarker(new MarkerOptions().position(latlng).title("Marker in local position")); mMap.moveCamera(CameraUpdateFactory.newLatLng(latlng)); } public void onStatusChanged(String provider, int status, Bundle extras) { } public void onProviderEnabled(String provider) { } public void onProviderDisabled(String provider) { } }; locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener); }catch(SecurityException ex){ Toast.makeText(this, ex.getMessage(), Toast.LENGTH_LONG).show(); } } |
Neste exemplo, usei um try/catch para suprimir a mensagem de erro de falta de permissão, desnecessária em Androids anteriores ao 6. Inclusive o próprio projeto já foi criado com a permissão de GPS devidamente adicionada no AndroidManifest.xml. Caso vá rodar este exemplo em um Android 6+, dê uma olhada na forma como pedi as permissões de GPS pro usuário corretamente no post sobre o GPS do Android.
Basicamente este código pega a informação de latitude e longitude atual fornecida pelo sensor de GPS e criar um marcador (pin, marker, etc) adicionando-o no mapa. Inclusive se você brincar via telnet com o seu emulador, consegue pinnar diversos locais usando o comandos geofix como abaixo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
MacBook-Pro-de-Luiz-Fernando-Duarte-Junior:~ luizfduartejr$ telnet localhost 5554 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. Android Console: Authentication required Android Console: type 'auth <auth_token>' to authenticate Android Console: you can find your <auth_token> in '/Users/luizfduartejr/.emulator_console_auth_token' OK auth /OYaznXpPMc6HJz5 Android Console: type 'help' for a list of commands OK geo fix -30 -51 OK geo fix -51 -30 OK geo fix 80 20 OK |
O que acaba adicionando diversos pins no mapa. Mas como resolver isso?
Nessa variação final, eu adiciono apenas um marker, e vou atualizando ele conforme as coordenadas do GPS mudem, evitando os múltiplos pins no mapa (que podem ser úteis em algum projeto seu também). Por padrão, defini que o marker fica apontando para Porto Alegre/RS.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
@Override public void onMapReady(GoogleMap googleMap) { mMap = googleMap; LatLng latlng = new LatLng(-30, -51); final Marker marker= mMap.addMarker(new MarkerOptions().position(latlng).title("Marker in local position")); try{ LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); LocationListener locationListener = new LocationListener() { public void onLocationChanged(Location location) { LatLng latlng = new LatLng(location.getLatitude(), location.getLongitude()); marker.setPosition(latlng); mMap.moveCamera(CameraUpdateFactory.newLatLng(latlng)); } public void onStatusChanged(String provider, int status, Bundle extras) { } public void onProviderEnabled(String provider) { } public void onProviderDisabled(String provider) { } }; locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener); }catch(SecurityException ex){ Toast.makeText(this, ex.getMessage(), Toast.LENGTH_LONG).show(); } } |
Lembrando que você pode alterar uma localização GPS fake no emulador facilmente pelos controles extendidos, usando as reticências na sidebar de apoio do emulador, conforme na imagem abaixo.
E por hoje é isso. O que achou deste tutorial? Funcionou para você? Deixe aí nos comentários a sua percepção!
Olá, tudo bem?
O que você achou deste conteúdo? Conte nos comentários.
Boa tarde.
Cara o app inicia mas não mostra o mapa…
Alguns pontos que você pode não ter reparado ao longo do tutorial:
– só funciona no simulador nativo usando uma imagem correta, chamada Google APIs
– se for usar outro simulador, tem um link no tutorial com mais instruções
– a primeira vez que você for executar, ele vai ficar em uma tela branca atualizando o Google Play Services. Vários minutos, dependendo da lentidão do simulador e da sua conexão de Internet.
Um abraço.
Bom dia, como voce esta fazendo para quando apertar o Botao ele aponte no mapa sua posição, estou testando direto no aparelho , moto g4 plus com android 7.0
No meu exemplo não tem botão, ele carrega automático. Mas acho que isso aqui pode te ajudar: https://github.com/googlemaps/android-samples/blob/master/ApiDemos/app/src/main/java/com/example/mapdemo/MyLocationDemoActivity.java
Boa noite,
Com é que eu faço para localizar um ônibus em tempo real
O ônibus deve ter hardware de GPS se comunicando com um servidor seu, para que você saiba onde ele está.
Como faço para criar novos pontos?
Como faço para criar novos pontos e traçar uma rota para esse novo ponto?
Boa noite. Você adiciona novos marcadores usando o método addMarker do mesmo jeito que usei para adicionar aquele ali. Para traçar rotas você terá de estudar a API Google Maps Directions, pois não tenho nenhum tutorial pronto sobre isso: https://developers.google.com/maps/documentation/directions/intro?hl=pt-br
Digo ao clicar, altetar o market que é criado automático e ir para um novo
No objeto de mapa (mMap) tem um removeMarker se não me engano, que tu usa pra remover o marcador. Daí com o addMarker tu adiciona outro. Não tenho nenhum projeto com mapa que eu possa compartilhar.
Teria algum projeto que usa o mapa, podendo criar uma nova marcação para eu ter como base em um app que estou desenvolvendo?