本页面由葡萄牙语机器翻译,可能存在错误。葡萄牙语版本为准。
如何获取 GPS 位置(纬度/经度)
目的。 获取设备的 纬度/经度。若只需一次性读取,使用 Location
retrieveGPSData();若需 持续跟踪,使用GPSThread,它会自行管理线程。
使用的 API
new Location() throws IOException— 打开 GPS(默认高精度)。也有new Location(int precision),可用Location.HIGH_GPS_PRECISION(仅 GPS)或Location.LOW_GPS_PRECISION(GPS + Google Play Services / 蜂窝 / wifi)。boolean retrieveGPSData()— 更新静态字段;获取到有效数据时返回true,信号弱时返回false(原因在Location.lowSignalReason中)。Location.getLatitude()/getLongitude()(静态)— 坐标;无信号时值为Location.INVALID。Location.velocity(单位为节/knots)、Location.pdop(精度因子)、Location.satellites、Location.direction— 静态字段。void stop()— 必需:关闭原生 API 并释放这个唯一实例。同一时刻只能有 一个Location打开(若已存在,构造函数会抛出IOException)。GPSThread(boolean highPrecision, int intervalInMS, Runnable onLocation, RunnableWith<Exception> onError)— 守护线程,在构造函数中 自行启动;stopGps()停止并等待其结束。
注意事项。 坐标字段是 静态的 —— 同一时刻只有一个活跃读取。始终 针对
Location.INVALID校验,并在信任位置前检查pdop(LOW 可能返回 30m–1500m+)。结束时调用stop()(GPSThread会在每个周期为你完成这件事)。
完整示例(复制、粘贴并运行)
package com.exemplo;
import dev.crossfly.ui.*; // Window, Component, Button, Label
import dev.crossfly.ui.layout.*; // VerticalLayout
import dev.crossfly.device.*; // Location, Device
/** 可执行的主界面。将 launcher 指向此类(classname)并运行: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 ->
{
// 单次读取(在 paint thread 之外)— 始终用 try/finally 确保 stop()
new Thread(() ->
{
Location loc = null;
try
{
loc = new Location(); // 打开 GPS(一次仅 1 个)
for (int i = 0; i < 120 && !loc.retrieveGPSData(); i++)
Device.sleep(500); // 最多等待约 60s 以获取定位
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)
{
// 已有一个 Location 打开,或打开 GPS 失败
Component.onUI(() -> resultado.setText("Erro: " + e.getMessage()));
}
finally
{
if (loc != null) loc.stop(); // 必须
}
}).start();
});
add(LAY_AUTO, acao);
}
}
下面的片段只展示 核心部分。要运行它,请把它放进上面的
MainWindow骨架里。
最小片段
// 已在源码验证: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) 单次读取(在 paint thread 之外)— 始终用 try/finally 确保 stop()
new Thread(() -> {
Location loc = null;
try {
loc = new Location(); // 打开 GPS(一次仅 1 个)
for (int i = 0; i < 120 && !loc.retrieveGPSData(); i++)
Device.sleep(500); // 最多等待约 60s 以获取定位
double lat = Location.getLatitude();
double lon = Location.getLongitude();
if (lat != Location.INVALID && lon != Location.INVALID)
Component.onUI(() -> mostrarPosicao(lat, lon)); // 返回在 paint thread 之外
} catch (java.io.IOException e) {
// 已有一个 Location 打开,或打开 GPS 失败
} finally {
if (loc != null) loc.stop(); // 必须
}
}).start();
// 2) 持续追踪 — GPSThread 自行启动;回调在 paint thread 之外
GPSThread gps = new GPSThread(true, 5000, // 高精度,每 5s 一次
() -> {
double lat = Location.getLatitude(), lon = Location.getLongitude();
Component.onUI(() -> atualizarMapa(lat, lon));
},
err -> Component.onUI(() -> mostrarErro(err.getMessage())));
// ... 结束时:
gps.stopGps();
深入了解
- 定位指南:Location & GPS
- 姊妹篇:escolher-local-no-mapa.md
这个页面有帮助吗?感谢你的反馈!