📍 Cap 17: PokeMap: Onde estão os Treinadores?
🎯 Objetivo da Aula: Ao final desta aula, você entenderá como o GPS do celular funciona. Você aprenderá a capturar sua localização atual (Latitude e Longitude) e mostrar um mapa interativo do Google no seu aplicativo.
🏢 O Cenário Prático (Seu Desafio): Você está criando o PokeMap. O desafio é mostrar no mapa onde existem “Ginásios Pokémon” na sua cidade. Para isso, o app precisa saber onde você está agora para calcular a distância até o ginásio mais próximo.
🧠 Fundamentos: A Teoria Traduzida
📖 Dicionário do Programador
- Latitude e Longitude: São os “endereços” matemáticos de qualquer lugar do planeta.
- Latitude: Norte/Sul.
- Longitude: Leste/Oeste.
- GPS: Sistema de satélites que diz ao celular exatamente onde ele está.
- Google Maps SDK: É a biblioteca que traz o mapa real do Google para dentro do seu app.
🎨 Padrão de Mapas
No Compose, usamos o componente GoogleMap. Para marcar um lugar específico, usamos um Marker (Pino).
graph LR
A[Satélite] --> B[Celular: Lat -23, Long -46]
B --> C{Mapa Google}
C --> D["Você está aqui!"]
🏗️ Construindo o Projeto (Checklist Studio)
Para o mapa funcionar, você precisará de duas coisas:
- Permissão de Localização: Adicione
ACCESS_FINE_LOCATIONno seu Manifesto. - API Key: Uma chave secreta que você gera no Google Cloud para o mapa abrir.
📦 Dependência Gradle
Para usar GoogleMap, Marker e LatLng no Compose, e para ler a localização real do GPS com FusedLocationProviderClient, adicione no build.gradle (Module: app), dentro de dependencies { }:
implementation 'com.google.maps.android:maps-compose:4.3.3'
implementation 'com.google.android.gms:play-services-maps:18.2.0'
implementation 'com.google.android.gms:play-services-location:21.2.0'
📦 Imports Necessários
Antes de copiar o código abaixo, adicione estes imports no topo do seu arquivo .kt:
import android.content.Context
import android.location.Location
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.ui.Modifier
import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.location.LocationServices
import com.google.android.gms.maps.model.LatLng
import com.google.maps.android.compose.GoogleMap
import com.google.maps.android.compose.Marker
import com.google.maps.android.compose.MarkerState
📖 Exemplo Passo a Passo: Colocando o Marcador
Parte 1 — O Mapa:
@Composable
fun MapaGinasio() {
val localGinasio = LatLng(-23.5505, -46.6333) // Coordenadas de exemplo
GoogleMap(modifier = Modifier.fillMaxSize()) {
// Colocando o pino no mapa
Marker(
state = MarkerState(position = localGinasio),
title = "Ginásio Master",
snippet = "Batalha de Nível 20"
)
}
}
Parte 2 — O GPS Real: o FusedLocationProviderClient é o “satélite” do Android. Ele entrega a última localização conhecida do celular via lastLocation, de forma assíncrona (addOnSuccessListener):
fun obterLocalizacaoAtual(context: Context) {
val cliente: FusedLocationProviderClient =
LocationServices.getFusedLocationProviderClient(context)
cliente.lastLocation.addOnSuccessListener { localizacao: Location? ->
if (localizacao != null) {
val minhaLat = localizacao.latitude
val minhaLong = localizacao.longitude
println("Você está em: $minhaLat, $minhaLong")
} else {
println("❌ Localização indisponível. O GPS está ativado?")
}
}
}
💡 Antes de chamar
obterLocalizacaoAtual, o app precisa que o usuário tenha aceitado a permissãoACCESS_FINE_LOCATION(Checklist Studio acima).
🛠️ Prática Obrigatória 1: Pesquise e anote as coordenadas de Latitude e Longitude de um lugar famoso na sua cidade ou no mundo (ex: Estátua da Liberdade).
🛠️ Prática Obrigatória 2:
Crie uma função chamada checarProximidade. Ela recebe a sua Latitude (Double) e a Latitude do Ginásio (Double). Se a diferença for menor que 0.001, o retorno deve ser "Você chegou ao Ginásio!".
🛠️ Prática Obrigatória 3:
Usando obterLocalizacaoAtual como referência, crie a função verificarChegada(context: Context, latGinasio: Double). Dentro do addOnSuccessListener, se localizacao não for nulo, chame checarProximidade(localizacao.latitude, latGinasio) e mostre o resultado com println.
🔑 Gabarito Passo a Passo:
Exercício 2:
fun checarProximidade(minhaLat: Double, ginasioLat: Double): String {
val diferenca = Math.abs(minhaLat - ginasioLat)
return if (diferenca < 0.001) {
"Você chegou ao Ginásio!"
} else {
"Continue andando..."
}
}
Exercício 3:
fun verificarChegada(context: Context, latGinasio: Double) {
val cliente: FusedLocationProviderClient =
LocationServices.getFusedLocationProviderClient(context)
cliente.lastLocation.addOnSuccessListener { localizacao: Location? ->
if (localizacao != null) {
val resultado = checarProximidade(localizacao.latitude, latGinasio)
println(resultado)
}
}
}
📤 Instruções de Entrega (Microsoft Teams):
- Envie as coordenadas que você pesquisou.
- Envie o código das funções
checarProximidadeeverificarChegada. - Submeta no canal de tarefas.