Android avançado no Kotlin 04.1: Google Maps no Android

1. Antes de começar

Ao criar apps com o Google Maps, você pode adicionar recursos como imagens de satélite, controles robustos de interface para mapas, rastreamento e marcadores de localização. Você pode agregar valor ao Google Maps padrão mostrando informações do seu próprio conjunto de dados, como os locais de áreas de pesca ou escalada conhecidas. Você também pode criar jogos em que o jogador explora o mundo físico, como uma caça ao tesouro ou até mesmo jogos de realidade aumentada.

Nesta lição, você vai criar um app do Google Maps chamado Wander, que mostra mapas personalizados e a localização do usuário.

Pré-requisitos

Conhecimento sobre:

  • Como criar e executar um app Android básico usando o Android Studio.
  • Como criar e gerenciar recursos, como strings.
  • Como refatorar código e renomear variáveis usando o Android Studio.
  • Como usar um mapa do Google como usuário.
  • Como definir permissões de tempo de execução.

O que você vai aprender

  • Como conseguir uma chave de API no Console de API do Google e registrar a chave no seu app
  • Como integrar um mapa do Google ao seu app
  • Como mostrar diferentes tipos de mapas
  • Como personalizar o estilo do mapa do Google
  • Como adicionar marcadores ao mapa
  • Como permitir que o usuário coloque um marcador em um ponto de interesse (PDI)
  • Como ativar o rastreamento de localização
  • Como criar o app Wander, que tem um mapa do Google Maps incorporado
  • Como criar recursos personalizados para seu app, como marcadores e estilos
  • Como ativar o rastreamento de localização no seu app

2. Visão geral do app

Neste codelab, você vai criar o app Wander, que mostra um mapa do Google com estilo personalizado. Com o app Wander, você pode colocar marcadores em locais, adicionar sobreposições e conferir sua localização em tempo real.

5b12eda7f467bc2f.png

3. Tarefa: configurar o projeto e receber uma chave de API

O SDK do Maps para Android exige uma chave de API. Para receber a chave de API, registre seu projeto na página "APIs e serviços". A chave de API está vinculada a um certificado digital que associa o app ao autor. Para mais informações sobre como usar certificados digitais e assinar seu app, consulte Assinar o app.

Neste codelab, você vai usar a chave de API do certificado de depuração. O certificado de depuração é inseguro por design, conforme descrito em Assinar sua build de depuração. Os apps Android publicados que usam o SDK do Maps para Android exigem uma segunda chave de API: a chave do certificado de lançamento. Para mais informações sobre como conseguir um certificado de lançamento, consulte Acessar uma chave de API.

O Android Studio inclui um modelo de atividade do Google Maps, que gera um código de modelo útil. O código do modelo inclui um arquivo google_maps_api.xml com um link que simplifica a obtenção de uma chave de API.

Etapa 1: criar o projeto Wander com o modelo de mapas

  1. Crie um novo projeto do Android Studio.
  2. Selecione o modelo Atividade no Google Maps.

d6b874bb19ea68cd.png

  1. Nomeie o projeto como Wander.
  2. Defina o nível mínimo da API como API 19. Confira se a linguagem é Kotlin.
  3. Clique em Concluir.
  4. Depois que o app for criado, confira o projeto e os seguintes arquivos relacionados a mapas que o Android Studio cria para você:

google_maps_api.xml: use esse arquivo de configuração para armazenar sua chave de API. O modelo gera dois arquivos google_maps_api.xml: um para depuração e outro para lançamento. O arquivo da chave de API do certificado de depuração está localizado em src/debug/res/values. O arquivo da chave de API do certificado de lançamento está localizado em src/release/res/values. Neste codelab, você vai usar apenas o certificado de depuração.

activity_maps.xml: esse arquivo de layout contém um único fragmento que preenche toda a tela. A classe SupportMapFragment é uma subclasse da classe Fragment. Um SupportMapFragment é a maneira mais simples de colocar um mapa em um app. Ele é um wrapper em torno de uma visualização de um mapa para processar automaticamente as necessidades necessárias do ciclo de vida.

Você pode incluir SupportMapFragment em um arquivo de layout usando uma tag <fragment> em qualquer ViewGroup, com um atributo name adicional.

android:name="com.google.android.gms.maps.SupportMapFragment"

MapsActivity.java: o arquivo MapsActivity.kt cria uma instância do SupportMapFragment no método onCreate() e usa o getMapAsync() da classe para inicializar automaticamente o sistema de mapas e a visualização. A atividade que contém o SupportMapFragment precisa implementar a interface OnMapReadyCallback e o método onMapReady() dessa interface. O método onMapReady() é chamado quando o mapa é carregado.

Etapa 2: receber a chave de API

  1. Abra a versão de depuração do arquivo google_maps_api.xml.
  2. No arquivo, procure um comentário com um URL longo. Os parâmetros do URL incluem informações específicas sobre seu app.
  3. Copie e cole o URL em um navegador.
  4. Siga as instruções para criar um projeto na página "APIs e serviços". Devido aos parâmetros no URL fornecido, a página sabe como ativar automaticamente o SDK do Maps para Android.
  5. Clique em Criar uma chave de API.
  6. Na próxima página, acesse a seção "Chaves de API" e clique na chave que você acabou de criar.
  7. Clique em Restringir chave e selecione SDK do Maps para Android para restringir o uso da chave a apps Android.
  8. Copie a chave de API gerada. Ela começa com "AIza".
  9. No arquivo google_maps_api.xml, cole a chave na string google_maps_key onde está escrito YOUR_KEY_HERE.
  10. Execute o app. Você vai ver um mapa incorporado na sua atividade com um marcador definido em Sydney, Austrália. O marcador de Sydney faz parte do modelo, e você pode mudá-lo depois.

34dc9dd877c90996.png

Etapa 3: renomear mMap

MapsActivity tem um lateinit var particular chamado mMap, que é do tipo GoogleMap. Para seguir as convenções de nomenclatura do Kotlin, mude o nome de mMap para map.

  1. Em MapsActivity, clique com o botão direito do mouse em mMap e clique em Refactor > Rename...

e713ccb3384450c6.png

  1. Mude o nome da variável para map.

Observe como todas as referências a mMap na função onMapReady() também mudam para map.

4. Tarefa: adicionar tipos de mapa

O Google Maps inclui vários tipos de mapa: normal, híbrido, satélite, terreno e "nenhum" (para não mostrar nenhum mapa).

Mapa normal

Mapa de satélite

Mapa híbrido

Mapa de terreno

Cada tipo de mapa fornece informações diferentes. Por exemplo, ao usar mapas para navegação em um carro, é útil ver os nomes das ruas. Nesse caso, use a opção normal. Ao fazer uma caminhada, o mapa de terreno pode ser útil para decidir quanto mais você precisa subir para chegar ao topo.

Nesta tarefa, você vai:

  1. Adicione uma barra de apps com um menu "opções" que permita ao usuário mudar o tipo de mapa.
  2. Mova o local de partida do mapa para o local da sua casa.
  3. Adicione suporte para marcadores, que indicam locais únicos em um mapa e podem incluir um rótulo.

Adicionar menu para tipos de mapa

Nesta etapa, você vai adicionar uma barra de apps com um menu "opções" que permite ao usuário mudar o tipo de mapa.

  1. Para criar um novo arquivo XML de menu, clique com o botão direito do mouse no diretório res e selecione New > Android Resource File.
  2. Na caixa de diálogo, nomeie o arquivo como map_options.
  3. Escolha Menu para o tipo de recurso.
  4. Clique em OK.
  5. Na guia Código, substitua o código no novo arquivo pelo seguinte para criar as opções do menu do mapa. O tipo de mapa "none" é omitido porque resulta na ausência de qualquer mapa. Essa etapa causa um erro, mas você vai resolver isso na próxima etapa.
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto">
   <item
       android:id="@+id/normal_map"
       android:title="@string/normal_map"
       app:showAsAction="never" />
   <item
       android:id="@+id/hybrid_map"
       android:title="@string/hybrid_map"
       app:showAsAction="never" />
   <item
       android:id="@+id/satellite_map"
       android:title="@string/satellite_map"
       app:showAsAction="never" />
   <item
       android:id="@+id/terrain_map"
       android:title="@string/terrain_map"
       app:showAsAction="never" />
</menu>
  1. Em strings.xml, adicione recursos para os atributos title e resolva os erros.
<resources>
   ...
   <string name="normal_map">Normal Map</string>
   <string name="hybrid_map">Hybrid Map</string>
   <string name="satellite_map">Satellite Map</string>
   <string name="terrain_map">Terrain Map</string>
   <string name="lat_long_snippet">Lat: %1$.5f, Long: %2$.5f</string>
   <string name="dropped_pin">Dropped Pin</string>
   <string name="poi">poi</string>
</resources>
  1. Em MapsActivity, substitua o método onCreateOptionsMenu() e infle o menu do arquivo de recurso map_options.
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
   val inflater = menuInflater
   inflater.inflate(R.menu.map_options, menu)
   return true
}
  1. Em MapsActivity.kt, substitua o método onOptionsItemSelected(). Mude o tipo de mapa usando constantes de tipo de mapa para refletir a seleção do usuário.
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
   // Change the map type based on the user's selection.
   R.id.normal_map -> {
       map.mapType = GoogleMap.MAP_TYPE_NORMAL
       true
   }
   R.id.hybrid_map -> {
       map.mapType = GoogleMap.MAP_TYPE_HYBRID
       true
   }
   R.id.satellite_map -> {
       map.mapType = GoogleMap.MAP_TYPE_SATELLITE
       true
   }
   R.id.terrain_map -> {
       map.mapType = GoogleMap.MAP_TYPE_TERRAIN
       true
   }
   else -> super.onOptionsItemSelected(item)
}
  1. Execute o app.
  2. Clique em 428da163b831115b.png para mudar o tipo de mapa. Observe como a aparência do mapa muda entre os diferentes modos.

6fa42970d87f5dc7.png

5. Tarefa: adicionar marcadores

Por padrão, o callback onMapReady() inclui um código que coloca um marcador em Sydney, Austrália, onde o Google Maps foi criado. O callback padrão também anima o mapa para fazer uma panorâmica em Sydney.

Nesta tarefa, você vai fazer a câmera do mapa se mover até sua casa, dar zoom até um nível especificado e colocar um marcador lá.

Etapa 1: aumentar o zoom na sua casa e adicionar um marcador

  1. No arquivo MapsActivity.kt, encontre o método onMapReady(). Remova o código que coloca o marcador em Sydney e move a câmera. O método vai ficar assim:
override fun onMapReady(googleMap: GoogleMap) {
   map = googleMap

}
  1. Para encontrar a latitude e a longitude da sua casa, siga estas instruções.
  2. Crie um valor para a latitude e outro para a longitude e insira os valores de ponto flutuante.
val latitude = 37.422160
val longitude = -122.084270
  1. Crie um novo objeto LatLng chamado homeLatLng. No objeto homeLatLng, transmita os valores que você acabou de criar.
val homeLatLng = LatLng(latitude, longitude)
  1. Crie um val para o nível de zoom que você quer usar no mapa. Use o nível de zoom 15f.
val zoomLevel = 15f

O nível de zoom controla o nível de ampliação do mapa. A lista a seguir mostra o nível de detalhamento de cada nível de zoom:

  • 1: Mundo
  • 5: terra/continente
  • 10: Cidade
  • 15: Ruas
  • 20: Prédios
  1. Mova a câmera para homeLatLng chamando a função moveCamera() no objeto map e transmita um objeto CameraUpdate usando CameraUpdateFactory.newLatLngZoom(). Transmita o objeto homeLatLng e o zoomLevel.
map.moveCamera(CameraUpdateFactory.newLatLngZoom(homeLatLng, zoomLevel))
  1. Adicione um marcador ao mapa em homeLatLng.
map.addMarker(MarkerOptions().position(homeLatLng))

O método final vai ficar assim:

override fun onMapReady(googleMap: GoogleMap) {
   map = googleMap

   //These coordinates represent the latitude and longitude of the Googleplex.
   val latitude = 37.422160
   val longitude = -122.084270
   val zoomLevel = 15f

   val homeLatLng = LatLng(latitude, longitude)
   map.moveCamera(CameraUpdateFactory.newLatLngZoom(homeLatLng, zoomLevel))
   map.addMarker(MarkerOptions().position(homeLatLng))
}
  1. Execute o app. O mapa vai se mover até sua casa, aumentar o zoom até o nível desejado e colocar um marcador nela.

fc939024778ee76.png

Etapa 2: permitir que os usuários adicionem um marcador com um clique longo

Nesta etapa, você vai adicionar um marcador quando o usuário tocar e pressionar um local no mapa.

  1. Crie um stub de método em MapsActivity chamado setMapLongClick() que receba um GoogleMap como argumento.
  2. Anexe um listener setOnMapLongClickListener ao objeto de mapa.
private fun setMapLongClick(map:GoogleMap) {
   map.setOnMapLongClickListener { }
}
  1. Em setOnMapLongClickListener(), chame o método addMarker(). Transmita um novo objeto MarkerOptions com a posição definida como o LatLng transmitido.
private fun setMapLongClick(map: GoogleMap) {
   map.setOnMapLongClickListener { latLng ->
       map.addMarker(
           MarkerOptions()
               .position(latLng)
       )
   }
}
  1. No final do método onMapReady(), chame setMapLongClick() com map.
override fun onMapReady(googleMap: GoogleMap) {
   ...
  
   setMapLongClick(map)
}
  1. Execute o app.
  2. Toque e pressione o mapa para colocar um marcador em um local.
  3. Toque no marcador para centralizá-lo na tela.

4ff8d1c1db3bca9e.png

Etapa 3: adicionar uma janela de informações ao marcador

Nesta etapa, você vai adicionar um InfoWindow que mostra as coordenadas do marcador quando ele é tocado.

  1. Em setMapLongClick()setOnMapLongClickListener(), crie um val para snippet. Um snippet é um texto adicional exibido após o título. O snippet mostra a latitude e a longitude de um marcador.
private fun setMapLongClick(map: GoogleMap) {
   map.setOnMapLongClickListener { latLng ->
       // A snippet is additional text that's displayed after the title.
       val snippet = String.format(
           Locale.getDefault(),
           "Lat: %1$.5f, Long: %2$.5f",
           latLng.latitude,
           latLng.longitude
       )
       map.addMarker(
           MarkerOptions()
               .position(latLng)
       )
   }
}
  1. Em addMarker(), defina o title do marcador como "Pino solto" usando um recurso de string R.string.dropped_pin.
  2. Defina o snippet do marcador como snippet.

A função concluída fica assim:

private fun setMapLongClick(map: GoogleMap) {
   map.setOnMapLongClickListener { latLng ->
       // A Snippet is Additional text that's displayed below the title.
       val snippet = String.format(
           Locale.getDefault(),
           "Lat: %1$.5f, Long: %2$.5f",
           latLng.latitude,
           latLng.longitude
       )
       map.addMarker(
           MarkerOptions()
               .position(latLng)
               .title(getString(R.string.dropped_pin))
               .snippet(snippet)
              
       )
   }
}
  1. Execute o app.
  2. Toque e mantenha pressionado o mapa para inserir um marcador de local.
  3. Toque no marcador para mostrar a janela de informações.

63f210e6e47dfa29.png

Etapa 4: adicionar um listener de PDI

Por padrão, os pontos de interesse (PDIs) aparecem no mapa com os respectivos ícones. Esses pontos incluem parques, escolas, edifícios governamentais e muito mais. Quando o tipo de mapa é definido como normal, os PDIs comerciais também aparecem no mapa. Esses pontos representam empresas, como lojas, restaurantes e hotéis.

Nesta etapa, você vai adicionar um GoogleMap.OnPoiClickListener ao mapa. Esse listener de clique coloca um marcador no mapa imediatamente quando o usuário clica em um PDI. O listener de clique também mostra uma janela de informações com o nome do PDI.

  1. Crie um stub de método em MapsActivity chamado setPoiClick() que receba um GoogleMap como argumento.
  2. No método setPoiClick(), defina um OnPoiClickListener no GoogleMap transmitido.
private fun setPoiClick(map: GoogleMap) {
   map.setOnPoiClickListener { poi ->

   }
}
  1. No setOnPoiClickListener(), crie um val poiMarker para o marcador .
  2. Defina como um marcador usando map.addMarker() com MarkerOptions definindo title como o nome do PDI.
private fun setPoiClick(map: GoogleMap) {
   map.setOnPoiClickListener { poi ->
       val poiMarker = map.addMarker(
           MarkerOptions()
               .position(poi.latLng)
               .title(poi.name)
       )
   }
}
  1. Na função setOnPoiClickListener(), chame showInfoWindow() em poiMarker para mostrar imediatamente a janela de informações.
poiMarker.showInfoWindow()

O código final da função setPoiClick() vai ficar assim:

private fun setPoiClick(map: GoogleMap) {
   map.setOnPoiClickListener { poi ->
       val poiMarker = map.addMarker(
           MarkerOptions()
               .position(poi.latLng)
               .title(poi.name)
       )
       poiMarker.showInfoWindow()
   }
}
  1. No final de onMapReady(), chame setPoiClick() e transmita map.
override fun onMapReady(googleMap: GoogleMap) {
   ...

   setPoiClick(map)
}
  1. Execute o app e encontre um PDI, como um parque ou uma cafeteria.
  2. Toque no PDI para colocar um marcador nele e mostrar o nome do PDI em uma janela de informações.

f4b0972c75d5fa5f.png

6. Tarefa: personalizar o estilo do mapa

Você pode personalizar o Google Maps de várias maneiras, ao seu mapa uma aparência única.

É possível personalizar um objeto MapFragment usando os atributos XML disponíveis, assim como qualquer outro fragmento. No entanto, nesta etapa, você personaliza a aparência do conteúdo do MapFragment usando métodos no objeto GoogleMap.

Para criar um estilo personalizado para seu mapa, gere um arquivo JSON que especifica como os recursos no mapa são mostrados. Não é necessário criar esse arquivo JSON manualmente. O Google oferece o assistente de estilo da Plataforma Google Maps, que gera o JSON para você depois que você estiliza o mapa visualmente. Nesta tarefa, você vai estilizar o mapa com um tema retrô, ou seja, ele vai usar cores vintage e você vai adicionar vias coloridas.

Etapa 1: criar um estilo para seu mapa

  1. Acesse https://mapstyle.withgoogle.com/ no navegador.
  2. Selecione Criar um estilo.
  3. Selecione Retro.

208b3d3aeab0d9b6.png

  1. Clique em Mais opções.

4a35faaf9535ee82.png

  1. Selecione Via > Preencher.
  2. Mude a cor das vias para qualquer cor que você escolher (como rosa).

92c3293749293a4c.png

  1. Clique em Concluir.

f1bfe8585eb69480.png

  1. Copie o código JSON da caixa de diálogo resultante e, se quiser, armazene-o em uma nota de texto simples para usar na próxima etapa.

3c32168b299d6420.png

Etapa 2: adicionar o estilo ao mapa

  1. No Android Studio, no diretório res, crie um diretório de recursos e nomeie-o como raw. Você usa os recursos do diretório raw como código JSON.
  2. Crie um arquivo em res/raw chamado map_style.json.
  3. Cole o código JSON armazenado no novo arquivo de recursos.
  4. Em MapsActivity, crie uma variável de classe TAG acima do método onCreate(). Isso é usado para fins de registro.
private val TAG = MapsActivity::class.java.simpleName
  1. Ainda em MapsActivity, crie uma função setMapStyle() que receba um GoogleMap.
  2. Em setMapStyle(), adicione um bloco try{}.
  3. No bloco try{}, crie um val success para o sucesso da estilização. (Adicione o seguinte bloco catch.)
  4. No bloco try{}, defina o estilo JSON para o mapa e chame setMapStyle() no objeto GoogleMap. Transmita um objeto MapStyleOptions, que carrega o arquivo JSON.
  5. Atribua o resultado a success. O método setMapStyle() retorna um booleano indicando o status de sucesso da análise do arquivo de estilo e da definição do estilo.
private fun setMapStyle(map: GoogleMap) {
   try {
       // Customize the styling of the base map using a JSON object defined
       // in a raw resource file.
       val success = map.setMapStyle(
           MapStyleOptions.loadRawResourceStyle(
               this,
               R.raw.map_style
           )
       )
   }
}
  1. Adicione uma instrução "if" para success ser falso. Se o estilo não for bem-sucedido, imprima um registro informando que a análise falhou.
private fun setMapStyle(map: GoogleMap) {
   try {
       ...
       if (!success) {
           Log.e(TAG, "Style parsing failed.")
       }
   }
}
  1. Adicione um bloco catch{} para lidar com a situação de um arquivo de estilo ausente. No bloco catch, se o arquivo não puder ser carregado, gere um Resources.NotFoundException.
private fun setMapStyle(map: GoogleMap) {
   try {
       ...
   } catch (e: Resources.NotFoundException) {
       Log.e(TAG, "Can't find style. Error: ", e)
   }
}

O método finalizado vai ficar parecido com este snippet de código:

private fun setMapStyle(map: GoogleMap) {
   try {
       // Customize the styling of the base map using a JSON object defined
       // in a raw resource file.
       val success = map.setMapStyle(
           MapStyleOptions.loadRawResourceStyle(
               this,
               R.raw.map_style
           )
       )

       if (!success) {
           Log.e(TAG, "Style parsing failed.")
       }
   } catch (e: Resources.NotFoundException) {
       Log.e(TAG, "Can't find style. Error: ", e)
   }
}
  1. Por fim, chame o método setMapStyle() no método onMapReady() transmitindo o objeto GoogleMap.
override fun onMapReady(googleMap: GoogleMap) {
   ...
   setMapStyle(map)
}
  1. Execute o app.
  2. Defina o mapa no modo normal. O novo estilo vai aparecer com o tema retrô e as vias na cor escolhida.

b59d6cb81f02a14f.png

Etapa 3: estilizar o marcador

Você pode personalizar ainda mais o mapa estilizando os marcadores. Nesta etapa, você vai mudar os marcadores vermelhos padrão para algo mais legal.

  1. No método onMapLongClick(), adicione a seguinte linha de código ao MarkerOptions() do construtor para usar o marcador padrão, mas mude a cor para azul.
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE))

Agora, o onMapLongClickListener() vai ficar assim:

map.setOnMapLongClickListener { latLng ->
   // A snippet is additional text that's displayed after the title.
   val snippet = String.format(
       Locale.getDefault(),
       "Lat: %1$.5f, Long: %2$.5f",
       latLng.latitude,
       latLng.longitude
   )
   map.addMarker(
       MarkerOptions()
           .position(latLng)
           .title(getString(R.string.dropped_pin))
           .snippet(snippet)
         .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE))
   )
}
  1. Execute o app. Os marcadores que aparecem depois de um clique longo agora estão sombreados em azul. Os marcadores de PDI ainda estão vermelhos porque você não adicionou estilo ao método onPoiClick().

b9916bca3c367e3.png

7. Tarefa: adicionar uma sobreposição

Uma maneira de personalizar o mapa do Google é desenhando sobre ele. Essa técnica é útil se você quiser destacar um tipo específico de local, como pontos de pesca populares.

  • Formas:você pode adicionar polilinhas, polígonos e círculos ao mapa.
  • Objetos GroundOverlay : uma sobreposição de solo é uma imagem fixa em um mapa. Ao contrário dos marcadores, as sobreposições de solo são orientadas para a superfície da Terra, e não para a tela. Girar, inclinar ou aumentar o zoom do mapa muda a orientação da imagem. Elas são úteis quando você quer corrigir uma única imagem em uma área do mapa.

Etapa: adicionar uma sobreposição de solo

Nesta tarefa, você vai adicionar uma sobreposição de solo em forma de Android ao local da sua casa.

  1. Faça o download desta imagem do Android e salve-a na pasta res/drawable. Verifique se o nome do arquivo é android.png.

61fabd56a0841b44.png

  1. Em onMapReady(), depois da chamada para mover a câmera até a posição da sua casa, crie um objeto GroundOverlayOptions.
  2. Atribua o objeto a uma variável chamada androidOverlay.
val androidOverlay = GroundOverlayOptions()
  1. Use o método BitmapDescriptorFactory.fromResource() para criar um objeto BitmapDescriptor do recurso de imagem baixado.
  2. Transmita o objeto BitmapDescriptor resultante para o método image() do objeto GroundOverlayOptions.
val androidOverlay = GroundOverlayOptions()
   .image(BitmapDescriptorFactory.fromResource(R.drawable.android))
  1. Crie um float overlaySize para a largura em metros da sobreposição desejada. Neste exemplo, uma largura de 100f funciona bem.

Defina a propriedade position para o objeto GroundOverlayOptions chamando o método position() e transmita o objeto homeLatLng e o overlaySize.

val overlaySize = 100f
val androidOverlay = GroundOverlayOptions()
   .image(BitmapDescriptorFactory.fromResource(R.drawable.android))
   .position(homeLatLng, overlaySize)
  1. Chame addGroundOverlay() no objeto GoogleMap e transmita o objeto GroundOverlayOptions.
map.addGroundOverlay(androidOverlay)
  1. Execute o app.
  2. Mude o valor de zoomLevel para 18f para ver a imagem do Android como uma sobreposição.

b1b25b0acd6a9807.png

8. Tarefa: ativar o rastreamento de localização

Os usuários costumam usar o Google Maps para ver a localização atual deles. Para mostrar a localização do dispositivo no mapa, use a camada de dados de localização.

A camada de dados de local adiciona o ícone Meu local ao mapa.

f317f84dcb3ac3a1.png

Quando o usuário toca no botão, o mapa é centralizado no local do dispositivo. A localização é mostrada como um ponto azul se o dispositivo estiver parado e como uma seta azul se estiver em movimento.

Nesta tarefa, você vai ativar a camada de dados de localização.

Etapa: solicitar permissões de localização

Para ativar o rastreamento de local no Google Maps, basta uma linha de código. No entanto, verifique se o usuário concedeu permissões de local (usando o modelo de permissão de tempo de execução).

Nesta etapa, você solicita permissões de localização e ativa o monitoramento de localização.

  1. No arquivo AndroidManifest.xml, verifique se a permissão FINE_LOCATION já está presente. O Android Studio inseriu essa permissão quando você selecionou o modelo do Google Maps.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  1. Em MapsActivity, crie uma variável de classe REQUEST_LOCATION_PERMISSION.
private val REQUEST_LOCATION_PERMISSION = 1
  1. Para verificar se as permissões foram concedidas, crie um método na MapsActivity chamado isPermissionGranted(). Nesse método, verifique se o usuário concedeu a permissão.
private fun isPermissionGranted() : Boolean {
  return ContextCompat.checkSelfPermission(
       this,
      Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
}
  1. Para ativar o rastreamento de localização no app, crie um método em MapsActivity chamado enableMyLocation() que não usa argumentos e não retorna nada. Dentro dele, verifique a permissão ACCESS_FINE_LOCATION. Se a permissão for concedida, ative a camada de localização. Caso contrário, solicite a permissão.
private fun enableMyLocation() {
   if (isPermissionGranted()) {
       map.isMyLocationEnabled = true 
   }
   else {
       ActivityCompat.requestPermissions(
           this,
           arrayOf<String>(Manifest.permission.ACCESS_FINE_LOCATION),
           REQUEST_LOCATION_PERMISSION
       )
   }
}
  1. Chame enableMyLocation() do callback onMapReady() para ativar a camada de local.
override fun onMapReady(googleMap: GoogleMap) {
   ...
   enableMyLocation()
}
  1. Modifique o método onRequestPermissionsResult(). Verifique se o requestCode é igual a REQUEST_LOCATION_PERMISSION. Se estiver, isso significa que a permissão foi concedida. Se a permissão for concedida, verifique também se a matriz grantResults contém PackageManager.PERMISSION_GRANTED no primeiro slot. Se isso for verdade, chame enableMyLocation().
override fun onRequestPermissionsResult(
   requestCode: Int,
   permissions: Array<String>,
   grantResults: IntArray) {
   if (requestCode == REQUEST_LOCATION_PERMISSION) {
       if (grantResults.contains(PackageManager.PERMISSION_GRANTED)) {
           enableMyLocation()
       }
   }
}
  1. Execute o app. Uma caixa de diálogo vai pedir acesso à localização do dispositivo. Conceda a permissão.

da7e23e00ec762c1.png

O mapa agora mostra o local atual do dispositivo usando um ponto azul. Observe que há um botão de localização. Se você mover o mapa para longe do seu local e clicar nesse botão, ele vai centralizar o mapa de volta no local do dispositivo.

5b12eda7f467bc2f.png

9. Código da solução

Faça o download do código do codelab concluído.

$  git clone https://github.com/googlecodelabs/android-kotlin-geo-maps

Se preferir, você pode baixar o repositório como um arquivo ZIP, descompactar e abrir no Android Studio.

10. Resumo

Parabéns! Você adicionou e estilizou um mapa do Google em um app Kotlin para Android.

11. Saiba mais

Documentação do desenvolvedor Android:

Documentação de referência:

12. Próximo codelab

Para acessar links de outros codelabs neste curso, consulte a página de destino dos codelabs do curso Android avançado no Kotlin.