Pular para o conteúdo
CrossFly é 100% open sourceSiga no GitHub
CrossFlyCrossFly
Começar

Como obter a posição GPS (latitude/longitude)

Propósito. Obter a latitude/longitude do dispositivo. Para uma leitura pontual use Location

  • retrieveGPSData(); para rastreamento contínuo use GPSThread, que já gerencia o thread.

APIs usadas

  • new Location() throws IOException — abre o GPS (precisão alta por padrão). Há também new Location(int precision) com Location.HIGH_GPS_PRECISION (só GPS) ou Location.LOW_GPS_PRECISION (GPS + Google Play Services / rádio / wifi).
  • boolean retrieveGPSData() — atualiza os campos estáticos; retorna true se obteve dado válido, false em sinal baixo (motivo em Location.lowSignalReason).
  • Location.getLatitude() / getLongitude() (estáticos) — coordenadas; valem Location.INVALID sem sinal.
  • Location.velocity (em nós/knots), Location.pdop (diluição de precisão), Location.satellites, Location.direction — campos estáticos.
  • void stop() — obrigatório: fecha a API nativa e libera a instância única. Só pode haver uma Location aberta por vez (o construtor lança IOException se já houver).
  • GPSThread(boolean highPrecision, int intervalInMS, Runnable onLocation, RunnableWith<Exception> onError) — thread daemon que inicia sozinha no construtor; stopGps() para e aguarda o término.

Cuidados. Os campos de coordenada são estáticos — só uma leitura ativa por vez. Sempre valide contra Location.INVALID e verifique o pdop antes de confiar na posição (LOW pode retornar 30m–1500m+). Chame stop() ao terminar (o GPSThread faz isso por você a cada ciclo).

Exemplo completo (copiar, colar e rodar)

package com.exemplo;

import dev.crossfly.ui.*;                   // Window, Component, Button, Label
import dev.crossfly.ui.layout.*;            // VerticalLayout
import dev.crossfly.device.*;               // Location, Device

/** Tela principal executável. Aponte o launcher (classname) e rode: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      Label resultado = new Label("");
      add(LAY_AUTO, resultado);

      Button acao = new Button("Obter GPS");
      acao.onAction(c ->
      {
         // Leitura pontual (fora da paint thread) — sempre em try/finally p/ garantir stop()
         new Thread(() ->
         {
            Location loc = null;
            try
            {
               loc = new Location();                              // abre o GPS (só 1 por vez)
               for (int i = 0; i < 120 && !loc.retrieveGPSData(); i++)
                  Device.sleep(500);                              // aguarda até ~60s por um fix
               double lat = Location.getLatitude();
               double lon = Location.getLongitude();
               if (lat != Location.INVALID && lon != Location.INVALID)
                  Component.onUI(() -> resultado.setText("Lat " + lat + " / Lon " + lon));
               else
                  Component.onUI(() -> resultado.setText("Sem sinal de GPS"));
            }
            catch (java.io.IOException e)
            {
               // já havia uma Location aberta, ou falha ao abrir o GPS
               Component.onUI(() -> resultado.setText("Erro: " + e.getMessage()));
            }
            finally
            {
               if (loc != null) loc.stop();                       // OBRIGATÓRIO
            }
         }).start();
      });
      add(LAY_AUTO, acao);
   }
}

O trecho abaixo mostra só o miolo. Para rodar, coloque-o no esqueleto MainWindow acima.

Trecho mínimo

// verificado na fonte: Location.java (Location(), retrieveGPSData, getLatitude/Longitude, INVALID, stop); GPSThread.java (constructor, stopGps)
import dev.crossfly.device.*;              // Location
import dev.crossfly.core.*;                // GPSThread
import dev.crossfly.ui.*;                  // Component (onUI)

// 1) Leitura pontual (fora da paint thread) — sempre em try/finally p/ garantir stop()
new Thread(() -> {
   Location loc = null;
   try {
      loc = new Location();                              // abre o GPS (só 1 por vez)
      for (int i = 0; i < 120 && !loc.retrieveGPSData(); i++)
         Device.sleep(500);                              // aguarda até ~60s por um fix
      double lat = Location.getLatitude();
      double lon = Location.getLongitude();
      if (lat != Location.INVALID && lon != Location.INVALID)
         Component.onUI(() -> mostrarPosicao(lat, lon)); // retorno fora da paint thread
   } catch (java.io.IOException e) {
      // já havia uma Location aberta, ou falha ao abrir o GPS
   } finally {
      if (loc != null) loc.stop();                       // OBRIGATÓRIO
   }
}).start();

// 2) Rastreamento contínuo — GPSThread inicia sozinha; callbacks fora da paint thread
GPSThread gps = new GPSThread(true, 5000,                // alta precisão, a cada 5s
   () -> {
      double lat = Location.getLatitude(), lon = Location.getLongitude();
      Component.onUI(() -> atualizarMapa(lat, lon));
   },
   err -> Component.onUI(() -> mostrarErro(err.getMessage())));
// ... quando terminar:
gps.stopGps();

Aprofunde-se

Esta página foi útil?