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

胖枫君_5965

胖枫君_5965

2026-05-20

225人浏览

原创

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

本文详解 Android 应用中因异步定位导致经纬度为 null 的典型问题,提供初始化防护、空值校验、权限与更新策略优化等完整解决方案,确保 pharmacy_latitude 和 pharmacy_longitude 可靠写入数据库。

本文详解 android 应用中因异步定位导致经纬度为 null 的典型问题,提供初始化防护、空值校验、权限与更新策略优化等完整解决方案,确保 `pharmacy_latitude` 和 `pharmacy_longitude` 可靠写入数据库。

在 Android 开发中,通过 LocationManager 获取用户当前位置并存入 SQLite 是常见需求,但实践中常出现 经纬度字段写入数据库后为 null 的问题——正如你在 saveData() 中观察到的:其他字段正常插入,唯独 PHARMACY_LATITUDE 和 PHARMACY_LONGITUDE 始终为空。根本原因在于:定位是异步操作,而 saveData() 很可能在 onLocationChanged() 回调执行前就被触发,此时未初始化的 pharmacy_lat/pharmacy_lon(默认为 null)被直接写入数据库。

✅ 正确做法:三重保障机制

1. 初始化 + 合理默认值(防 null 入库)

不要依赖 Double 成员变量的默认 null,应在声明时赋予安全初始值(如 0.0),并在数据库建表时保持类型一致(推荐 REAL 而非 TEXT):

// ✅ 推荐:使用 double(基本类型)避免 null,并设合理默认值
private double pharmacy_lat = 0.0;
private double pharmacy_lon = 0.0;

⚠️ 注意:你的建表语句中定义为 " TEXT NOT NULL",但实际应存数值。建议修改为:

PHARMACY_LATITUDE REAL NOT NULL, PHARMACY_LONGITUDE REAL NOT NULL

并在 ContentValues 中使用 put(String key, double value) 方法。

Android Remote Control
Android Remote Control

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

下载

2. 写入前强制校验(核心修复)

在 saveData() 中加入位置有效性判断,拒绝无效坐标写入:

private void saveData() {
    // ? 关键校验:确保经纬度已成功获取且有效(排除 0.0 的默认值或明显异常值)
    if (pharmacy_lat == 0.0 && pharmacy_lon == 0.0) {
        Toast.makeText(this, "⚠️ 位置信息尚未获取,请稍候再试", Toast.LENGTH_SHORT).show();
        return;
    }

    // ✅ 安全写入:使用 double 类型自动转换
    ContentValues cvDoctor = new ContentValues();
    cvDoctor.put(Queryclass.PHARMACY_LATITUDE, pharmacy_lat);   // 自动装箱为 Double
    cvDoctor.put(Queryclass.PHARMACY_LONGITUDE, pharmacy_lon);

    // ... 其他字段赋值(略)

    sd.insert(Queryclass.TABLE_PHARMA, cvDoctor);
}

3. 优化定位逻辑(提升可靠性)

  • 使用 FusedLocationProviderClient(推荐):比过时的 LocationManager 更省电、更精准、支持回调超时;
  • 添加超时与失败兜底:避免用户长时间无响应;
  • 检查定位是否启用:在请求更新前验证 GPS/WiFi 是否开启。

简易升级示例(兼容 API 21+):

private FusedLocationProviderClient fusedLocationClient;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // ...
    fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);

    if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
            == PackageManager.PERMISSION_GRANTED) {
        getLastKnownLocation();
    }
}

private void getLastKnownLocation() {
    fusedLocationClient.getLastLocation()
        .addOnSuccessListener(this, location -> {
            if (location != null) {
                pharmacy_lat = location.getLatitude();
                pharmacy_lon = location.getLongitude();
                Log.d("Location", "Got: " + pharmacy_lat + ", " + pharmacy_lon);
            } else {
                requestLocationUpdates(); // 回退到实时更新
            }
        })
        .addOnFailureListener(this, e -> requestLocationUpdates());
}

private void requestLocationUpdates() {
    LocationRequest request = LocationRequest.create()
        .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
        .setInterval(10_000)
        .setMaxWaitTime(30_000);

    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
        fusedLocationClient.requestLocationUpdates(request, locationCallback, Looper.getMainLooper());
    }
}

private final LocationCallback locationCallback = new LocationCallback() {
    @Override
    public void onLocationResult(@NonNull LocationResult locationResult) {
        if (locationResult != null && !locationResult.getLocations().isEmpty()) {
            Location location = locationResult.getLastLocation();
            pharmacy_lat = location.getLatitude();
            pharmacy_lon = location.getLongitude();
            fusedLocationClient.removeLocationUpdates(locationCallback); // ✅ 主动移除
        }
    }
};

? 总结与最佳实践

  • 永远不要假设异步操作已完成:定位回调与 UI 操作(如点击保存)无顺序保证;
  • 初始化防御 + 运行时校验 = 双保险:既防 null 入库,也防误触;
  • 优先使用 FusedLocationProviderClient:Google Play 强制要求,且体验更优;
  • 数据库字段类型匹配:REAL 存经纬度,语义清晰、查询高效;
  • 用户提示友好化:明确告知“位置未就绪”,而非静默失败。

遵循以上方案,即可彻底解决经纬度存库为 null 的顽疾,构建健壮、可维护的位置采集模块。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

android

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
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

Gradle插件开发入门教程
Gradle插件开发入门教程

本专题介绍Gradle插件开发的基本流程,涵盖插件类编写、自定义任务注册、扩展参数设计和插件应用方法,帮助你理解插件如何组织构建逻辑,减少多个项目之间的重复配置。

2026.10.22

0

11

Gradle Wrapper配置教程
Gradle Wrapper配置教程

本专题介绍Gradle Wrapper的基本作用,涵盖文件组成、生成方法、版本配置和任务调用,帮助你理解项目如何使用指定的Gradle版本,减少不同开发环境带来的构建差异。

2026.10.22

0

10

Golangci-lint检查器使用教程
Golangci-lint检查器使用教程

本专题整理Golangci-lint常用Linters的用途与配置方法,覆盖错误处理、无效代码、安全、复杂度、命名和依赖检查,帮助项目合理选规则。

2026.10.22

0

15

热门下载

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

精品课程

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

共162课时 | 44.6万人学习

Java 教程
Java 教程

共578课时 | 193.1万人学习

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

共64课时 | 9.6万人学习