Avançado do Android 09.1: Google Maps

1. Olá

Este codelab faz parte do curso de treinamento de desenvolvimento avançado para Android, desenvolvido pela equipe de treinamento do Google Developers. Você vai aproveitar mais este curso se fizer os codelabs em sequência.

Para detalhes completos sobre o curso, consulte a visão geral do desenvolvimento avançado para Android.

Introdução

Ao criar apps com o Google Maps, você pode adicionar recursos como imagens de satélite, controles robustos de interface, rastreamento e marcadores de localização. Você pode adicionar 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 vinculados ao mundo real, como o Pokémon Go.

Neste exercício prático, você vai criar um app do Google Maps chamado Wander.

O que você já precisa saber

Você precisa:

  • Funcionalidade básica do Google Maps.
  • Permissões de execução.
  • Criar, criar e executar apps no Android Studio.
  • Incluir bibliotecas externas no arquivo build.gradle.

O que você vai aprender

  • Integre um mapa do Google ao seu app.
  • Mostrar diferentes tipos de mapas.
  • Personalize o estilo do mapa do Google.
  • Adicione marcadores ao mapa.
  • Permite que o usuário coloque um marcador em um ponto de interesse (PDI).
  • Ative o rastreamento de localização.
  • Ative o Google Street View.

Atividades deste laboratório

  • Receba uma chave de API do Console de API do Google e registre-a no seu app.
  • Crie o app Wander, que tem um mapa do Google incorporado.
  • Adicione recursos personalizados ao seu app, como marcadores, estilos e rastreamento de localização.
  • Ative o rastreamento de localização e o Street View no seu app.

2. Visão geral do app

Neste exercício prático, você vai criar o app Wander, que é um mapa do Google estilizado. Com o app Wander, é possível colocar marcadores em locais, ver sua localização em tempo real e conferir panoramas do Street View.

Um mapa do Google estilizado

Google Street View em um app Android

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

A API Google Maps, assim como a API Places, exige uma chave de API. Para receber a chave de API, registre seu projeto no Console de APIs do Google. A chave de API está vinculada a um certificado digital que associa o app ao autor. Para saber mais sobre como usar certificados digitais e assinar seu app, consulte Assinar seu app.

Neste exercício prático, você vai usar a chave de API para o 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 a API Google Maps 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 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.

1.1 Criar o projeto Wander com o modelo do Maps

  1. Crie um novo projeto do Android Studio.
  2. Nomeie o novo app como "Wander". Aceite os padrões até chegar à página Adicionar uma atividade.
  3. Selecione o modelo Atividade no Google Maps.
  4. Mantenha os valores padrão em Nome da atividade e Nome do layout.
  5. Mude o Título para "Wander" e clique em Concluir.

O Android Studio cria vários arquivos adicionais relacionados a mapas:

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 para o certificado de depuração está localizado em src/debug/res/values. O arquivo da chave de API para o certificado de lançamento está localizado em src/release/res/values. Neste exercício prático, vamos 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. É possível incluir SupportMapFragment em um arquivo de layout usando uma tag <fragment> em qualquer ViewGroup, com um atributo adicional:

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

MapsActivity.java

O arquivo MapsActivity.java cria uma instância da classe SupportMapFragment e usa o método getMapAsync() da classe para preparar o mapa do Google. A atividade que contém o SupportMapFragment precisa implementar a interface OnMapReadyCallback e o método onMapReady() dessa interface. O método getMapAsync() retorna um objeto GoogleMap, indicando que o mapa foi carregado.

1.2 Receber a chave de API

  1. Abra a versão de depuração do arquivo google_maps_api.xml.

O arquivo inclui um comentário com um URL longo. Os parâmetros do URL incluem informações específicas sobre seu app.

  1. Copie e cole o URL em um navegador.
  2. Siga as instruções para criar um projeto no Console de APIs do Google. Devido aos parâmetros no URL fornecido, o console de APIs sabe como ativar automaticamente a API Google Maps para Android.
  3. Crie uma chave de API e clique em Restringir chave para limitar o uso da chave a apps Android. A chave de API gerada precisa começar com AIza.
  4. No arquivo google_maps_api.xml, cole a chave na string google_maps_key onde está escrito YOUR_KEY_HERE.
  5. Execute o app. Você tem um mapa incorporado na atividade, com um marcador definido em Sydney, Austrália. O marcador de Sydney faz parte do modelo, e você pode mudá-lo depois.

4. Tarefa 2: Adicionar tipos de mapa e marcadores

O Google Maps inclui vários tipos de mapa: normal, híbrido, satélite, terreno e "nenhum". Nesta tarefa, você vai adicionar uma barra de apps com um menu "opções" que permite ao usuário mudar o tipo de mapa. Você move o local inicial do mapa para o local da sua casa. Em seguida, adicione suporte para marcadores, que indicam locais únicos em um mapa e podem incluir um rótulo.

2.1 Adicionar tipos de mapa

O tipo de mapa que o usuário quer depende do tipo de informação que ele precisa. Ao usar mapas para navegação no carro, é útil ver os nomes das ruas com clareza. Ao fazer uma caminhada, você provavelmente se importa mais com o quanto precisa subir para chegar ao topo da montanha. 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 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. Escolha Menu para o tipo de recurso. Clique em OK.
  3. Substitua o código no novo arquivo pelo seguinte para criar as opções de mapa. O tipo de mapa "none" é omitido porque resulta na ausência de qualquer mapa.
<?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. Crie recursos de string para os atributos title.
  2. No arquivo MapsActivity, mude a classe para estender a classe AppCompatActivity em vez da classe FragmentActivity. Usar AppCompatActivity vai mostrar a barra de apps e, portanto, o menu.
  3. Em MapsActivity, substitua o método onCreateOptionsMenu() e faça a inclusão do arquivo map_options:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
   MenuInflater inflater = getMenuInflater();
   inflater.inflate(R.menu.map_options, menu);
   return true;
}
  1. Para mudar o tipo de mapa, use o método setMapType() no objeto GoogleMap, transmitindo uma das constantes de tipo de mapa.

Modifique o método onOptionsItemSelected(). Cole o código a seguir para mudar o tipo de mapa quando o usuário selecionar uma das opções do menu:

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
       // Change the map type based on the user's selection.
       switch (item.getItemId()) {
           case R.id.normal_map:
               mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
               return true;
           case R.id.hybrid_map:
               mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
               return true;
           case R.id.satellite_map:
               mMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
               return true;
           case R.id.terrain_map:
               mMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
               return true;
           default:
               return super.onOptionsItemSelected(item);
       }
    }
  1. Execute o app. Use o menu na barra de apps para mudar o tipo de mapa. Observe como a aparência do mapa muda.

2.2 Mover o local padrão do mapa

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 etapa, você faz o mapa rolar até a localização da sua casa sem colocar um marcador e depois aumenta o zoom até um nível especificado.

  1. No método onMapReady(), remova o código que coloca o marcador em Sydney e move a câmera.
  2. Acesse www.google.com/maps no navegador e encontre sua casa.
  3. Clique com o botão direito do mouse no local e selecione O que há aqui?

Perto da parte de baixo da tela, uma pequena janela aparece com informações de localização, incluindo latitude e longitude.

  1. Crie um novo objeto LatLng chamado home. No objeto LatLng, use as coordenadas encontradas no Google Maps no navegador.
  2. Crie uma variável float chamada zoom e defina o nível de zoom inicial desejado. 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. Crie um objeto CameraUpdate usando CameraUpdateFactory.newLatLngZoom(), transmitindo o objeto LatLng e a variável zoom. Faça panorâmica e zoom na câmera chamando moveCamera() no objeto GoogleMap e transmitindo o novo objeto CameraUpdate:
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(home, zoom));
  1. Execute o app. O mapa vai se mover para sua casa e aumentar o zoom no nível desejado.

2.3 Adicionar marcadores de mapa

O Google Maps pode destacar um local usando um marcador, que você cria com a classe Marker. O marcador padrão usa o ícone padrão do Google Maps: Marcador do Google Maps

É possível estender os marcadores para mostrar informações contextuais em janelas de informações.

Nesta etapa, você vai adicionar um marcador quando o usuário tocar e pressionar um local no mapa. Em seguida, adicione um InfoWindow que mostre as coordenadas do marcador quando ele for tocado.

Uma janela de informações para um marcador fixado

  1. Crie um stub de método em MapsActivity chamado setMapLongClick() que recebe um GoogleMap final como argumento e retorna void:
private void setMapLongClick(final GoogleMap map) {}
  1. Use o método setOnMapLongClickListener() do objeto GoogleMap para colocar um marcador onde o usuário toca e mantém pressionado. Transmita uma nova instância de OnMapLongClickListener que substitui o método onMapLongClick(). O argumento de entrada é um objeto LatLng que contém as coordenadas do local em que o usuário pressionou:
private void setMapLongClick(final GoogleMap map) {
   map.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() {
       @Override
       public void onMapLongClick(LatLng latLng) {
       }
   });
}
  1. Em onMapLongClick(), chame o método addMarker(). Transmita um novo objeto MarkerOptions com a posição definida como o LatLng transmitido:
map.addMarker(new MarkerOptions().position(latLng));
  1. Chame setMapLongClick() no final do método onMapReady(). Transmita mMap.
  2. Execute o app. Toque e pressione no mapa para colocar um marcador em um local.
  3. Toque no marcador para centralizá-lo na tela.

Os botões de navegação aparecem na parte de baixo à esquerda da tela, permitindo que o usuário use o app Google Maps para navegar até a posição marcada.

Para adicionar uma janela de informações ao marcador:

  1. No objeto MarkerOptions, defina os campos title e snippet.
  2. Em onMapLongClick(), defina o campo title como "Pino solto". Defina o campo snippet como as coordenadas de local no método addMarker().
map.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() {
   @Override
   public void onMapLongClick(LatLng latLng) {
       String snippet = String.format(Locale.getDefault(),
               "Lat: %1$.5f, Long: %2$.5f",
               latLng.latitude,
               latLng.longitude);

       map.addMarker(new MarkerOptions()
               .position(latLng)
               .title(getString(R.string.dropped_pin))
               .snippet(snippet));
   }
});
  1. Execute o app. Toque e pressione no mapa para inserir um marcador de local. Toque no marcador para mostrar a janela de informações.

2.4 Adicionar 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, em vez de esperar um toque e manter pressionado. O listener de clique também mostra a janela de informações que contém o nome do PDI.

Marcador de ponto de interesse

  1. Crie um stub de método em MapsActivity chamado setPoiClick() que receba um GoogleMap final como argumento e retorne void:
private void setPoiClick(final GoogleMap map) {}
  1. No método setPoiClick(), defina um OnPoiClickListener no GoogleMap transmitido:
map.setOnPoiClickListener(new GoogleMap.OnPoiClickListener() {
   @Override
   public void onPoiClick(PointOfInterest poi) {
   }
});
  1. No método onPoiClick(), coloque um marcador no local do PDI. Defina o título como o nome do PDI. Salve o resultado em uma variável chamada poiMarker.
public void onPoiClick(PointOfInterest poi) {
   Marker poiMarker = mMap.addMarker(new MarkerOptions()
       .position(poi.latLng)
       .title(poi.name);
}
  1. Chame showInfoWindow() em poiMarker para mostrar a janela de informações imediatamente.
poiMarker.showInfoWindow();
  1. Chame setPoiClick() no final de onMapReady(). Transmita mMap.
  2. Execute o app e encontre um PDI, como um parque. Toque no PDI para colocar um marcador nele e mostrar o nome do PDI em uma janela de informações.

5. Tarefa 3: Personalizar seu 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. Use o Assistente de estilo on-line para adicionar um estilo ao mapa e personalizar os marcadores. Você também pode adicionar um GroundOverlay ao local da sua casa que é dimensionado e gira com o mapa.

3.1 Adicionar um estilo ao mapa

Para criar um estilo personalizado para seu mapa, gere um arquivo JSON que especifica como os recursos no mapa são exibidos.Não é necessário criar esse arquivo JSON manualmente: o Google oferece o Assistente de estilo, que gera o JSON para você depois que você estiliza visualmente seu mapa. Neste exercício prático, você vai estilizar o mapa para o "modo noturno", ou seja, ele vai usar cores escuras e baixo contraste para uso à noite.

  1. Acesse https://mapstyle.withgoogle.com/ no navegador.
  2. Selecione Criar um estilo.
  3. Selecione o tema Noite.
  4. Clique em Mais opções na parte de baixo do menu.
  5. Na parte de baixo da lista Tipo de recurso, selecione Água > Preenchimento. Mude a cor da água para um azul-escuro (por exemplo, #160064).
  6. Clique em Concluir. Copie o código JSON da janela pop-up resultante.
  7. No Android Studio, crie um diretório de recursos chamado raw no diretório res. Crie um arquivo em res/raw chamado map_style.json.
  8. Cole o código JSON no novo arquivo de recursos.
  9. Para definir o estilo JSON no mapa, chame setMapStyle() no objeto GoogleMap. Transmita um objeto MapStyleOptions, que carrega o arquivo JSON. O método setMapStyle() retorna um booleano indicando o sucesso da estilização. Se não for possível carregar o arquivo, o método vai gerar uma Resources.NotFoundException.

Copie o código abaixo no método onMapReady() para estilizar o mapa. Talvez seja necessário criar uma string TAG para suas instruções de registro:

     try {
        // Customize the styling of the base map using a JSON object defined
        // in a raw resource file.
        boolean success = googleMap.setMapStyle(
           MapStyleOptions.loadRawResourceStyle(
                   this, R.raw.map_style));

        if (!success) {
            Log.e(TAG, "Style parsing failed.");
        }
     } catch (Resources.NotFoundException e) {
        Log.e(TAG, "Can't find style. Error: ", e);
     }
  1. Execute o app. O novo estilo vai aparecer quando o mapa estiver no modo normal.

Mapa do Google no estilo do modo noturno

3.2 Estilizar o marcador

Você pode personalizar ainda mais o mapa estilizando os marcadores. Nesta etapa, você muda os marcadores vermelhos padrão para corresponder ao esquema de cores do modo noturno.

  1. No método onMapLongClick(), adicione a seguinte linha de código ao construtor MarkerOptions() para usar o marcador padrão, mas mudar a cor para azul:
.icon(BitmapDescriptorFactory.defaultMarker
       (BitmapDescriptorFactory.HUE_BLUE))
  1. Execute o app. Os marcadores que você coloca agora estão sombreados em azul, o que é mais consistente com o tema do modo noturno do app.

Os marcadores de PDIs ainda estão vermelhos porque você não adicionou estilo ao método onPoiClick().

3.3 Adicionar uma sobreposição

Uma maneira de personalizar o Google Maps é desenhando sobre ele. Essa técnica é útil se você quiser destacar um tipo específico de local, como pontos de pesca populares. Há suporte para três tipos de overlays:

  • Formas: você pode adicionar polilinhas, polígonos e círculos ao mapa.
  • Objetos TileOverlay: uma sobreposição de blocos define um conjunto de imagens adicionadas sobre os blocos do mapa de base. As sobreposições de blocos são úteis para adicionar várias imagens ao mapa. Uma sobreposição de blocos típica cobre uma grande área geográfica.
  • 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.

Nesta etapa, 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.
  2. Em onMapReady(), depois da chamada para mover a câmera para a posição inicial, crie um objeto GroundOverlayOptions. Atribua o objeto a uma variável chamada homeOverlay:
GroundOverlayOptions homeOverlay = new GroundOverlayOptions();
  1. Use o método BitmapDescriptorFactory.fromResource() para criar um objeto BitmapDescriptor com base na imagem acima. Transmita o objeto para o método image() do objeto GroundOverlayOptions:
GroundOverlayOptions homeOverlay = new GroundOverlayOptions()
    .image(BitmapDescriptorFactory.fromResource(R.drawable.android));
  1. Defina a propriedade position para o objeto GroundOverlayOptions chamando o método position(). Transmita o objeto home LatLng e um float para a largura em metros da sobreposição desejada. Para este exemplo, uma largura de 100 m funciona bem:
GroundOverlayOptions homeOverlay = new GroundOverlayOptions()
     .image(BitmapDescriptorFactory.fromResource(R.drawable.android))
       .position(home, 100);
  1. Chame addGroundOverlay() no objeto GoogleMap. Transmita o objeto GroundOverlayOptions:
mMap.addGroundOverlay(homeOverlay);
  1. Execute o app. Aumente o zoom no local da sua casa para ver a imagem do Android como uma sobreposição.

6. Tarefa 4: Ativar o rastreamento de localização e o Street View

Os usuários costumam usar o Google Maps para ver a localização atual, e você pode obter a localização do dispositivo usando a API Serviços de localização. Para mostrar a localização do dispositivo no mapa sem usar mais dados de Location, use a camada de dados de local.

A camada de dados de local adiciona um botão Meu local no canto superior direito do mapa. 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.

Um mapa estilizado do Google com monitoramento de localização

Você pode fornecer mais informações sobre um local usando o Google Street View, que é uma foto panorâmica navegável de um determinado local.

Nesta tarefa, você vai ativar a camada de dados de localização e o Street View para que, quando o usuário tocar na janela de informações do marcador de PDI, o mapa entre no modo Street View.

4.1 Ativar o rastreamento 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.
  2. Para ativar o rastreamento de localização no app, crie um método na MapsActivity chamado enableMyLocation() que não usa argumentos e não retorna nada.
  3. Defina o método enableMyLocation(). Verifique se você tem 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 void enableMyLocation() {
   if (ContextCompat.checkSelfPermission(this,
           Manifest.permission.ACCESS_FINE_LOCATION)
           == PackageManager.PERMISSION_GRANTED) {
       mMap.setMyLocationEnabled(true);
   } else {
       ActivityCompat.requestPermissions(this, new String[]
                       {Manifest.permission.ACCESS_FINE_LOCATION},
               REQUEST_LOCATION_PERMISSION);
   }
}
  1. Chame enableMyLocation() do callback onMapReady() para ativar a camada de local.
  2. Modifique o método onRequestPermissionsResult(). Se a permissão for concedida, chame enableMyLocation():
@Override
public void onRequestPermissionsResult(int requestCode,
       @NonNull String[] permissions,
       @NonNull int[] grantResults) {
   // Check if location permissions are granted and if so enable the
   // location data layer.
   switch (requestCode) {
       case REQUEST_LOCATION_PERMISSION:
           if (grantResults.length > 0
                   && grantResults[0]
                   == PackageManager.PERMISSION_GRANTED) {
               enableMyLocation();
               break;
           }
   }
}
  1. Execute o app. O canto superior direito agora contém o botão Meu local, que mostra a localização atual do dispositivo.

4.2 Ativar o Street View

O Google Maps oferece o Street View, que é uma visualização panorâmica de um local com controles para navegar por um caminho designado. O Street View não tem cobertura global.

Nesta etapa, você vai ativar um panorama do Street View que é ativado quando o usuário toca na janela de informações de um PDI. Você precisa fazer duas coisas:

  1. Distinga os marcadores de PDIs de outros marcadores, porque você quer que a funcionalidade do app funcione apenas nos marcadores de PDIs. Assim, você pode iniciar o Street View quando o usuário tocar em uma janela de informações de um POI, mas não quando ele tocar em qualquer outro tipo de marcador.

A classe Marker inclui um método setTag() que permite anexar dados. Os dados podem ser qualquer coisa que se estenda de Object. Você vai definir uma tag nos marcadores criados quando os usuários clicam em PDIs.

  1. Quando o usuário tocar em uma janela de informações marcada em um OnInfoWindowClickListener, substitua o MapFragment por um StreetViewPanoramaFragment. O código abaixo usa SupportMapFragment e SupportStreetViewPanoramaFragment para oferecer suporte a versões do Android anteriores à API 12.

Se algum dos fragmentos mudar durante a execução, adicione-os na classe Activity que os contém, e não de forma estática em XML.

Marcar o marcador de PDI

  1. No callback onPoiClick(), chame setTag() em poiMarker. Transmita qualquer string arbitrária:
poiMarker.setTag("poi");

Substituir o SupportMapFragment estático por uma instância de tempo de execução

  1. Abra activity_maps.xml e mude o elemento para um layout de frame que vai servir como contêiner dos seus fragmentos:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:id="@+id/fragment_container"
   android:layout_width="match_parent"
   android:layout_height="match_parent" />
  1. Em onCreate() em MapsActivity, remova o código que encontra o SupportMapFragment por ID, porque não há mais um SupportMapFragment estático no XML. Em vez disso, crie uma nova instância de ambiente de execução do SupportMapFragment chamando SupportMapFragment.newInstance():
SupportMapFragment mapFragment = SupportMapFragment.newInstance();
  1. Adicione o fragmento ao FrameLayout usando uma transação de fragmento com o FragmentManager:
getSupportFragmentManager().beginTransaction()
       .add(R.id.fragment_container, mapFragment).commit();
  1. Mantenha a linha de código que aciona o carregamento assíncrono do mapa:
mapFragment.getMapAsync(this);

Definir um OnInfoWindowClickListener e verificar a tag do marcador

  1. Crie um stub de método em MapsActivity chamado setInfoWindowClickToPanorama() que recebe um GoogleMap como argumento e retorna void:
private void setInfoWindowClickToPanorama(GoogleMap map) {}
  1. Defina um OnInfoWindowClickListener para o GoogleMap:
map.setOnInfoWindowClickListener(
       new GoogleMap.OnInfoWindowClickListener() {
           @Override
           public void onInfoWindowClick(Marker marker) {
           }
       });
  1. No método onInfoWindowClick(), verifique se o marcador contém a tag de string definida no método onPoiClick():
if (marker.getTag() == "poi") {}

Substitua o SupportMapFragment por um SupportStreetViewPanoramaFragment

  1. Se o marcador tiver a tag, especifique o local do panorama do Street View usando um objeto StreetViewPanoramaOptions. Defina a propriedade position do objeto como a posição do marcador transmitido:
StreetViewPanoramaOptions options =
       new StreetViewPanoramaOptions().position(
               marker.getPosition());
  1. Crie uma nova instância de SupportStreetViewPanoramaFragment, transmitindo o objeto options que você criou:
SupportStreetViewPanoramaFragment streetViewFragment
       = SupportStreetViewPanoramaFragment
       .newInstance(options);
  1. Inicie uma transação de fragmento. Substitua o conteúdo do contêiner de fragmentos pelo novo fragmento, streetViewFragment. Adicione a transação ao backstack para que, ao pressionar "Voltar", a navegação retorne ao SupportMapFragment e não saia do app:
getSupportFragmentManager().beginTransaction()
       .replace(R.id.fragment_container,
               streetViewFragment)
       .addToBackStack(null).commit();
  1. Chame setInfoWindowClickToPanorama(mMap) em onMapReady() depois da chamada para setPoiClick()..
  2. Execute o app. Aumente o zoom em uma cidade com cobertura do Street View, como Mountain View (sede do Google), e encontre um PDI, como um parque. Toque no PDI para colocar um marcador e mostrar a janela de informações. Toque na janela de informações para entrar no modo Street View do local do marcador. Pressione o botão "Voltar" para retornar ao fragmento do mapa.

Google Street View em um app Android

7. Código da solução

Código da solução Wander.

8. Desafio de programação

Desafio:se você tocar na janela de informações de um PDI em um local sem cobertura do Street View, uma tela preta vai aparecer.

9. Resumo

  • Para usar a API Maps, você precisa de uma chave de API do Console de APIs do Google.
  • No Android Studio, usar o modelo de atividade do Google Maps gera um Activity com um único SupportMapFragment no layout do app. O modelo também adiciona o ACCESS_FINE_PERMISSION ao manifesto do app, implementa o OnMapReadyCallback na sua atividade e substitui o método onMapReady() necessário.

Para mudar o tipo de mapa de um GoogleMap durante a execução, use o método GoogleMap.setMapType(). Um mapa do Google pode ser um dos seguintes tipos:

  • Normal: mapa rodoviário comum. Mostra vias, alguns elementos criados pelo homem e recursos naturais importantes, como rios. Marcadores de estradas e de elementos também são visíveis.
  • Híbrido: dados de fotografia de satélite com mapas rodoviários. Marcadores de estradas e de elementos também são visíveis.
  • Satélite: dados de fotografia. Os rótulos de vias e recursos não são visíveis.
  • Terreno: dados topográficos. O mapa inclui cores, curva de nível e marcadores, além de sombreamento de perspectiva. Algumas vias e etiquetas também são visíveis.
  • Nenhum: nenhum mapa.

Sobre o Google Maps:

  • Um marcador é um indicador de uma localização geográfica específica.
  • Quando alguém toca no marcador, o comportamento padrão é mostrar uma janela de informações com detalhes sobre o local.
  • Por padrão, os pontos de interesse (POIs, na sigla em inglês) aparecem no mapa de base junto com seus respectivos ícones. Esses pontos incluem parques, escolas, edifícios governamentais e muito mais.
  • Além disso, os PDIs de empresas (lojas, restaurantes, hotéis e outros) aparecem por padrão no mapa quando o tipo dele é normal.
  • É possível capturar cliques em PDIs usando o OnPoiClickListener.
  • É possível mudar a aparência visual de quase todos os elementos de um mapa do Google usando o Assistente de estilo. O assistente de estilo gera um arquivo JSON que você transmite para o Google Maps usando o método setMapStyle().
  • Você pode personalizar os marcadores mudando a cor padrão ou substituindo o ícone padrão por uma imagem personalizada.

Outras informações importantes:

  • Use uma sobreposição de solo para fixar uma imagem em uma localização geográfica.
  • Use um objeto GroundOverlayOptions para especificar a imagem, o tamanho dela em metros e a posição. Transmita esse objeto ao método GoogleMap.addGroundOverlay() para definir a sobreposição no mapa.
  • Desde que o app tenha a permissão ACCESS_FINE_LOCATION, é possível ativar o rastreamento de localização usando o método mMap.setMyLocationEnabled(true).
  • O Street View do Google proporciona visualizações panorâmicas de 360 graus de vias designadas em toda sua área de cobertura.
  • Use o método StreetViewPanoramaFragment.newInstance() para criar um novo fragmento do Street View.
  • Para especificar as opções da visualização, use um objeto StreetViewPanoramaOptions. Transmita o objeto para o método newInstance().

10. Saiba mais

A documentação do conceito relacionado está em 9.1: API Google Maps.

Documentação do desenvolvedor Android:

Documentação de referência:

11. Dever de casa

Esta seção lista as possíveis atividades de dever de casa para os alunos que estão fazendo este codelab como parte de um curso ministrado por um professor. Cabe ao professor fazer o seguinte:

  • Atribuir o dever de casa, se necessário.
  • Informar aos alunos como enviar deveres de casa.
  • Atribuir nota aos deveres de casa.

Os professores podem usar essas sugestões o quanto quiserem, podendo passar os exercícios que acharem mais apropriados como dever de casa.

Se você estiver seguindo este codelab por conta própria, sinta-se à vontade para usar esses deveres de casa para testar seu conhecimento.

Criar e executar um app

  1. Crie um app que use o modelo de atividade do Google Maps, que carrega o Google Maps quando o app é iniciado.
  2. Quando o mapa do Google for carregado, mova a câmera para o local da escola, da sua casa ou de algum outro lugar importante para você.
  3. Adicione dois marcadores ao mapa, um no local da escola e outro na sua casa ou em algum outro lugar importante.
  4. Personalize os ícones de marcador mudando a cor padrão ou substituindo o ícone padrão por uma imagem personalizada.

Dica:consulte a documentação do onMapReady (GoogleMap googleMap).

Responda estas perguntas

Pergunta 1

Qual método é chamado quando o mapa é carregado e está pronto para ser usado no app?

Pergunta 2

Quais componentes do Android podem ser usados para incluir o Google Maps no seu app?

  • MapView e MapFragment
  • MapFragment e MapActivity
  • MapView e MapActivity
  • Somente MapFragment

Pergunta 3

Quais tipos de mapas a API Google Maps para Android oferece?

  • Normal, híbrido, relevo, satélite e roteiro
  • Normal, híbrido, terreno, satélite e "nenhum"
  • Híbrido, terreno, satélite, roteiro e "nenhum"
  • Normal, terreno, satélite, imagem de mapa e "nenhum"

Pergunta 4

Qual interface você implementa para adicionar funcionalidade de clique a um ponto de interesse (PDI)?

  • GoogleMap.OnPoiListener
  • GoogleMap.OnPoiClickListener
  • GoogleMap.OnPoiClick
  • GoogleMap.OnPoiClicked

Enviar o app para avaliação

Orientação para os avaliadores

Verifique se o app tem estes recursos:

  • Quando o app é iniciado, o Google Maps é exibido corretamente, indicando que uma chave de API foi gerada de maneira adequada.
  • Depois que o Google Maps carregar, a câmera vai se mover para a casa ou a escola do estudante. No código, essa etapa precisa acontecer no método de callback onMapReady (GoogleMap googleMap).
  • Os marcadores são exibidos no local da escola do estudante e em outro local, como a casa dele.
  • Os dois marcadores são personalizados. Por exemplo, os marcadores usam uma cor diferente do vermelho padrão ou um ícone personalizado.

12. Próximo codelab

Para conferir todos os codelabs do curso de treinamento Desenvolvimento avançado para Android, acesse a página de destino dos codelabs de Desenvolvimento avançado para Android.