如何在 Android 中正确获取用户经纬度并保存到 SQLite 数据库

雨强吖_8812

雨强吖_8812

2026-05-20

860人浏览

原创

如何在 Android 中正确获取用户经纬度并保存到 SQLite 数据库

本文详解 Android 应用中因异步定位导致经纬度为 null 的典型问题,提供初始化、权限校验、定位回调与保存逻辑的完整解决方案,确保 pharmacy_latitude 和 pharmacy_longitude 可靠写入 SQLite。

本文详解 android 应用中因异步定位导致经纬度为 null 的典型问题,提供初始化、权限校验、定位回调与保存逻辑的完整解决方案,确保 `pharmacy_latitude` 和 `pharmacy_longitude` 可靠写入 sqlite。

在 Android 开发中,通过 LocationManager 获取用户当前位置并存入 SQLite 是常见需求,但极易因异步定位机制与同步保存逻辑的时间错位而失败——正如您所遇:pharmacy_lat 和 pharmacy_lon 在调试器中可见,却始终以 null 写入数据库。根本原因在于:saveData() 被调用时,onLocationChanged() 尚未执行,而 Double pharmacy_lat, pharmacy_lon; 作为对象类型,默认值为 null(非 0.0),且未做空值防护,直接传入 ContentValues 后被 SQLite 解析为 NULL。

✅ 正确实践:四步闭环保障定位数据可靠入库

1. 声明即初始化,杜绝默认 null

// ❌ 错误:未初始化,初始值为 null
// Double pharmacy_lat, pharmacy_lon;

// ✅ 正确:显式初始化为 0.0(或使用 Double.NaN 表示“未获取”)
private double pharmacy_lat = 0.0;   // 建议用基本类型 double,避免 null
private double pharmacy_lon = 0.0;

? 使用 double(基本类型)而非 Double(包装类),可彻底规避 NullPointerException 风险;若需区分“未定位”和“定位为 0”,可用 Double.NaN 初始化,并用 Double.isNaN(pharmacy_lat) 判断。

Android Remote Control
Android Remote Control

远程控制 Android 设备,支持截图、自动化操作手机 App 等功能。本应用使用 uiautomator2 作为底层框架,通过 ADB 连接设备,用户无需 Root(1)查看手机屏幕;(2)自动化操作手机 App;(3)远程安装/卸载应用……

下载

2. 强化定位回调:确保单次有效更新

locationListener = new LocationListener() {
    @Override
    public void onLocationChanged(@NonNull Location location) {
        if (location != null && location.getLatitude() != 0.0 && location.getLongitude() != 0.0) {
            pharmacy_lat = location.getLatitude();
            pharmacy_lon = location.getLongitude();
            // ✅ 关键:移除监听,避免重复赋值或旧数据覆盖
            locationManager.removeUpdates(this);
            Log.d("Location", "Fetched: lat=" + pharmacy_lat + ", lon=" + pharmacy_lon);
        }
    }

    // ⚠️ 补充:处理定位不可用场景(如 GPS 关闭)
    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
        if (status == LocationProvider.OUT_OF_SERVICE) {
            Log.w("Location", "Provider " + provider + " is out of service");
        }
    }
};

3. 保存前严格校验:拒绝无效坐标

private void saveData() {
    // ✅ 校验定位是否成功获取(使用基本类型后,无需判 null)
    if (pharmacy_lat == 0.0 && pharmacy_lon == 0.0) {
        Toast.makeText(this, "⚠️ 位置信息尚未获取,请稍候再试", Toast.LENGTH_SHORT).show();
        return;
    }

    // ✅ 进一步校验地理合理性(可选但推荐)
    if (Math.abs(pharmacy_lat) > 90 || Math.abs(pharmacy_lon) > 180) {
        Toast.makeText(this, "❌ 获取的位置数据异常,请检查定位服务", Toast.LENGTH_LONG).show();
        return;
    }

    // 继续执行原有 ContentValues 构建与插入逻辑...
    ContentValues cvDoctor = new ContentValues();
    cvDoctor.put(Queryclass.PHARMACY_LATITUDE, String.valueOf(pharmacy_lat)); // 存为 TEXT 字段
    cvDoctor.put(Queryclass.PHARMACY_LONGITUDE, String.valueOf(pharmacy_lon));

    // ... 其他字段赋值(略)
    sd.insert(Queryclass.TABLE_PHARMA, cvDoctor);
}

4. 增强健壮性:添加超时与备选定位源

// 在 onCreate 中请求定位后,启动超时检测
private static final long LOCATION_TIMEOUT_MS = 30_000; // 30秒
private Handler timeoutHandler = new Handler(Looper.getMainLooper());
private Runnable timeoutRunnable = () -> {
    Toast.makeText(this, "? 定位超时,将使用最后已知位置(如有)", Toast.LENGTH_LONG).show();
    Location lastKnown = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
    if (lastKnown != null) {
        pharmacy_lat = lastKnown.getLatitude();
        pharmacy_lon = lastKnown.getLongitude();
    }
};

// 请求定位后立即 post 超时任务
timeoutHandler.postDelayed(timeoutRunnable, LOCATION_TIMEOUT_MS);

// 在 onLocationChanged 中及时移除超时任务
@Override
public void onLocationChanged(@NonNull Location location) {
    // ... 获取坐标逻辑
    timeoutHandler.removeCallbacks(timeoutRunnable); // ✅ 清除超时
}

? 关键注意事项总结

  • 不要依赖 GPS_PROVIDER 单一来源:在室内或信号弱时可能长时间无回调,建议同时尝试 NETWORK_PROVIDER 或使用 FusedLocationProviderClient(推荐 AndroidX 新 API)。
  • SQLite 字段类型匹配:若数据库定义为 TEXT NOT NULL,请确保传入 String.valueOf(lat);若为 REAL NOT NULL,则传 Double 值本身。
  • 权限动态申请必须在 UI 线程:您的 requestPermissions 已正确实现,但需确保 saveData() 不在 onRequestPermissionsResult 返回前被意外触发(例如按钮未置灰)。
  • 生命周期安全:在 onPause() 中调用 locationManager.removeUpdates(locationListener),防止内存泄漏。

通过以上结构化改进,您将彻底解决经纬度存为 null 的问题,实现稳定、可维护的地理数据采集与持久化流程。

相关专题

更多
location.assign
location.assign

在前端开发中,我们经常需要使用JavaScript来控制页面的跳转和数据的传递。location.assign就是JavaScript中常用的一个跳转方法。通过location.assign,我们可以在当前窗口或者iframe中加载一个新的URL地址,并且可以保存旧页面的历史记录。php中文网为大家带来了location.assign的相关知识、以及相关文章等内容,供大家免费下载使用。

2023.06.27

2822

5

android开发三大框架
android开发三大框架

android开发三大框架是XUtil框架、volley框架、ImageLoader框架。本专题为大家提供android开发三大框架相关的各种文章、以及下载和课程。

2023.08.14

902

4

android是什么系统
android是什么系统

Android是一种功能强大、灵活可定制、应用丰富、多任务处理能力强、兼容性好、网络连接能力强的操作系统。本专题为大家提供android相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.22

2687

5

android权限限制怎么解开
android权限限制怎么解开

android权限限制可以使用Root权限、第三方权限管理应用程序、ADB命令和Xposed框架解开。详细介绍:1、Root权限,通过获取Root权限,用户可以解锁所有权限,并对系统进行自定义和修改;2、第三方权限管理应用程序,用户可以轻松地控制和管理应用程序的权限;3、ADB命令,用户可以在设备上执行各种操作,包括解锁权限;4、Xposed框架,用户可以在不修改系统文件的情况下修改应用程序的行为和权限。

2023.09.19

5197

7

android重启应用的方法有哪些
android重启应用的方法有哪些

android重启应用有通过Intent、PendingIntent、系统服务、Runtime等方法。本专题为大家提供Android相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.18

665

5

Android语音播放功能实现方法
Android语音播放功能实现方法

实现方法有使用MediaPlayer实现、使用SoundPool实现两种。可以根据具体的需求选择适合的方法进行实现。想了解更多语音播放的相关内容,可以阅读本专题下面的文章。

2024.03.01

964

5

Playwright 测试失败怎么办
Playwright 测试失败怎么办

Playwright测试失败专题汇集超时、定位器匹配、浏览器提前关闭、依赖与插件配置、文件上传、SSL及Docker启动等故障文章,并介绍通过截图、报告和Trace定位错误。

2026.10.21

20

15

Playwright 页面操作指南
Playwright 页面操作指南

Playwright页面操作专题汇集元素定位、点击与输入、等待响应、多页面切换、Iframe、事件监听及文件处理的已审核文章,便于按操作场景查阅示例与常见问题。

2026.10.21

0

16

Playwright 入门教程
Playwright 入门教程

Playwright入门专题汇集测试框架安装、VS Code配置、录制脚本、编写首个用例、运行调试及查看报告的已审核文章,帮助初学者搭建端到端测试流程。

2026.10.21

0

16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Excel 教程
Excel 教程

共162课时 | 44.6万人学习

Java 教程
Java 教程

共578课时 | 193.1万人学习

Uniapp从零开始实现新闻资讯应用
Uniapp从零开始实现新闻资讯应用

共64课时 | 9.6万人学习