Android跑步App实战:高德地图SDK集成与轨迹绘制
简介这是一份基于 Android Studio 与 Java 开发的运动跑步类 App 完整源码面向具备一定安卓基础、希望学习定位与运动数据可视化的开发者可用于课程设计、毕业设计或二次开发。项目围绕跑步场景实现实时速度记录、跑步路径绘制、历史数据管理与详情查看等核心功能并集成地图 SDK 完成轨迹展示。压缩包共 129 个文件约 18.03MB包含 22 个 java 源码文件、32 个 xml 布局与配置、56 个 png 图片资源以及 so 库、jar 包和 gradle 构建脚本结构完整、可直接导入 Android Studio 运行调试。目前已有 2540 人学习下载适合作为安卓定位与运动类应用的实战参考帮助读者理解地图轨迹绘制、数据持久化与界面组织方式快速搭建自己的跑步记录工具。1. 从一份只有 9 个文件的 Android 跑步 App 说起一个能跑起来的安卓跑步 App核心文件可能比你想象的少得多。这份资源里只有gradlew.bat、两个.gitignore、两个build.gradle、settings.gradle、gradlew、一个高德地图 SDK 的 jar 包、一个gradle-wrapper.jar以及一个mapActivity.java。没有花哨的架构没有 MVVM没有 Jetpack Compose就是一个 Activity 扛起实时速度、路径绘制、履历管理和数据详情四件事。适合谁适合刚学完 Android 基础、想找一个能跑通「定位 地图 数据持久化」闭环的练手项目的人也适合需要快速验证高德地图 SDK 在 Android Studio 里怎么接的开发者。它解决的不是「做一个商业级跑步软件」而是「让你在半天内看到一个真实可运行的定位轨迹 Demo 长什么样」。下面按「资源是什么 → 怎么用 → 坑在哪」的顺序拆开讲。2. 环境搭建与 Gradle 配置把项目从压缩包跑到模拟器2.1 为什么这个项目用高德地图而不是 Google Maps国内安卓设备上 Google Play 服务缺失是常态用 Google Maps SDK 的结果就是地图一片空白定位回调也不触发。高德地图 SDK 在国内的定位精度和覆盖度是经过验证的Android_Map3D_SDK_V6.8.0_20190401.jar这个文件名本身就说明了版本——3D 地图、6.8.0、2019 年 4 月 1 日构建。选它不是因为先进而是因为稳。这个 jar 包直接放在项目根目录说明作者没有走 Maven 仓库依赖而是手动集成。手动集成的好处是不依赖网络拉取坏处是你得自己处理 so 库和权限。常见做法是去高德开放平台申请一个 Key然后在AndroidManifest.xml里配com.amap.api.v2.apikey。这个项目里没有 manifest 文件说明它可能只保留了核心逻辑文件你需要自己补一个完整的 Android 项目壳。我一般会先用 Android Studio 新建一个 Empty Activity 项目再把mapActivity.java和 jar 包挪进去。2.2 从零补全项目结构的操作步骤第一步新建项目。Android Studio 里选 Empty Views Activity语言选 Java最低 SDK 建议设到 API 23Android 6.0因为高德 6.8.0 的定位权限在 6.0 以上需要动态申请。第二步放 jar 包。在app模块下新建libs目录把Android_Map3D_SDK_V6.8.0_20190401.jar复制进去然后在app/build.gradle里加一行dependencies { implementation files(libs/Android_Map3D_SDK_V6.8.0_20190401.jar) // 高德地图 6.8.0 还需要对应的 so 库通常放在 jniLibs 下 // 如果只有 jar 没有 so地图会加载失败报 native library not found }第三步配权限。在AndroidManifest.xml里加定位和网络权限uses-permission android:nameandroid.permission.ACCESS_FINE_LOCATION / uses-permission android:nameandroid.permission.ACCESS_COARSE_LOCATION / uses-permission android:nameandroid.permission.INTERNET / uses-permission android:nameandroid.permission.WRITE_EXTERNAL_STORAGE / !-- Android 10 需要后台定位的话还要加 ACCESS_BACKGROUND_LOCATION --第四步在 manifest 的application标签里写 Keymeta-data android:namecom.amap.api.v2.apikey android:value你申请到的高德Key /第五步把mapActivity.java注册进去activity android:name.mapActivity /这五步做完Sync 一下 Gradle如果报Duplicate class或者Program type already present说明你同时引了高德的 Maven 依赖和本地 jar二选一即可。这个项目是本地 jar 路线就把 Maven 那行删掉。2.3 Gradle 版本与 Android Studio 版本的匹配gradle-wrapper.jar和gradlew的存在说明项目用的是 Gradle Wrapper。但 wrapper 的版本写在gradle/wrapper/gradle-wrapper.properties里这个文件不在资源列表中所以你需要自己指定。2019 年的项目大概率用的是 Gradle 5.x 或 6.x对应 Android Studio 3.5 到 4.0。如果你现在用 Android Studio 2023 以后的版本Gradle 8.x 会直接报Unsupported class file major version。我的做法是不纠结原版 Gradle 版本直接用当前 Android Studio 新建项目的 Gradle 配置只把mapActivity.java和 jar 包移植过去。因为 Gradle 配置是壳业务逻辑在 Java 文件里。移植时注意build.gradle里的compileSdkVersion和targetSdkVersion要改成你本地已有的 SDK 版本否则会卡在下载 SDK 那一步。提示如果你在gradlew.bat双击后窗口一闪而过不要慌这是正常的——它需要在命令行里执行而且要在项目根目录下执行gradlew tasks才能看到输出。3. mapActivity 里的定位与轨迹绘制实时速度和路径怎么落地的3.1 定位回调与速度计算的代码逻辑mapActivity.java是这个项目唯一的核心类。它要同时做四件事拿定位、画路径、算速度、存数据。高德 SDK 的定位用法是AMapLocationClient加AMapLocationListener。下面是我根据这个项目的功能描述还原出来的关键代码结构public class mapActivity extends AppCompatActivity implements AMapLocationListener { private AMapLocationClient locationClient; private AMap aMap; private Polyline runningPath; // 跑步路径折线 private ListLatLng pathPoints new ArrayList(); private double currentSpeed 0.0; Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_map); // 初始化地图 MapView mapView findViewById(R.id.map_view); mapView.onCreate(savedInstanceState); aMap mapView.getMap(); // 初始化定位 locationClient new AMapLocationClient(getApplicationContext()); AMapLocationClientOption option new AMapLocationClientOption(); option.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy); option.setInterval(2000); // 2 秒回调一次跑步场景够用 locationClient.setLocationOption(option); locationClient.setLocationListener(this); locationClient.startLocation(); } Override public void onLocationChanged(AMapLocation location) { if (location null || location.getErrorCode() ! 0) return; // 速度高德直接返回 m/s转成 km/h 更符合跑步习惯 currentSpeed location.getSpeed() * 3.6; LatLng newPoint new LatLng(location.getLatitude(), location.getLongitude()); pathPoints.add(newPoint); // 每次回调更新折线 if (runningPath null) { runningPath aMap.addPolyline(new PolylineOptions() .addAll(pathPoints) .width(10) .color(Color.RED)); } else { runningPath.setPoints(pathPoints); } // 地图视角跟随 aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(newPoint, 17)); } }逻辑说明setInterval(2000)是定位回调间隔单位毫秒。跑步时 2 秒一次足够画出平滑路径设成 1000 会明显增加耗电。location.getSpeed()返回的是米每秒乘以 3.6 转成公里每小时这是跑步 App 的通用做法。Polyline是折线每次回调把新点加进列表再setPoints比每次addPolyline更省内存。参数说明Hight_Accuracy是高精度模式会同时用 GPS 和网络定位室内可能漂移如果只测跑步可以改成Device_Sensors只用 GPS但首次定位会慢。newLatLngZoom的第二个参数是缩放级别17 大约能看到街道级别跑步时够用。3.2 跑步履历的数据持久化方案履历管理意味着每次跑步结束要存一条记录包含日期、距离、时长、平均速度、路径点。这个项目没有提到数据库但常见做法是两种SQLite 或文件存储。SQLite 更适合「查看数据详细」这种需要按 ID 查询的场景。我一般会建一张run_record表CREATE TABLE run_record ( id INTEGER PRIMARY KEY AUTOINCREMENT, start_time TEXT NOT NULL, distance REAL DEFAULT 0, duration INTEGER DEFAULT 0, avg_speed REAL DEFAULT 0, path_json TEXT );path_json存的是路径点的 JSON 数组比如[{lat:39.9,lng:116.4},...]。这样查详情时直接反序列化就能在地图上重绘。距离计算用高德AMapUtils.calculateLineDistance(startLatLng, endLatLng)逐段累加不要用经纬度差值乘系数那个误差在长距离下会大到离谱。写入时机是用户点「结束跑步」按钮时把pathPoints转成 JSON算好总距离和总时长插一条记录。查询履历就是SELECT * FROM run_record ORDER BY start_time DESC点某一条再按 ID 查详情。3.3 地图生命周期与 Activity 的绑定高德MapView必须和 Activity 生命周期同步否则会内存泄漏或者黑屏。在mapActivity里要重写onResume、onPause、onDestroy、onSaveInstanceStateOverride protected void onResume() { super.onResume(); mapView.onResume(); } Override protected void onPause() { super.onPause(); mapView.onPause(); } Override protected void onDestroy() { super.onDestroy(); if (locationClient ! null) { locationClient.stopLocation(); locationClient.onDestroy(); } mapView.onDestroy(); }这段代码是血泪经验不写onDestroy里的stopLocation退出页面后定位还在跑用户手机发烫不说后台还会持续耗电。不写mapView.onDestroy()下次进页面地图直接白屏。4. 避坑与常见问题从编译失败到定位漂移的排查清单4.1 编译期报错Duplicate class 和 SDK 版本不匹配现象Sync 后报Duplicate class com.amap.api.maps.AMap found in modules。原因同时引了高德 Maven 依赖和本地 jar。解决检查build.gradle的 dependencies只保留implementation files(libs/Android_Map3D_SDK_V6.8.0_20190401.jar)删掉任何com.amap.api:map3d之类的远程依赖。现象报Unsupported class file major version 61。原因Gradle 版本太低跑不了 Java 17 编译的代码。解决升级gradle-wrapper.properties里的distributionUrl到 Gradle 7.5 以上或者把 Android Studio 的 Gradle JDK 改成 Java 11。4.2 运行期问题地图空白与定位不回调现象App 装上去地图是灰的没有网格也没有路。原因高德 Key 没配或者配错位置。解决确认AndroidManifest.xml的application标签内写了com.amap.api.v2.apikey且 Key 的包名和签名与申请时一致。调试版和发布版签名不同Key 也要分别申请。现象定位回调一直不触发onLocationChanged不执行。原因Android 6.0 以上没有动态申请权限。解决在onCreate里加ActivityCompat.requestPermissions申请ACCESS_FINE_LOCATION用户拒绝后要引导去设置页开权限。另外模拟器上定位可能返回 0,0建议用真机测。4.3 数据层面的坑速度跳变和路径锯齿现象静止时速度显示 3 km/h 以上或者跑步时速度突然跳到 50。原因GPS 漂移导致相邻两个点距离计算异常。解决加一个过滤逻辑如果location.getAccuracy() 50就丢弃这个点或者用滑动平均取最近 3 个点的速度均值。现象路径画出来是锯齿状的不像真实跑步路线。原因定位点太少或者间隔太长。解决把setInterval从 2000 改成 1000同时开启setNeedAddress(false)减少网络请求。但要注意间隔越短耗电越快跑步场景 1 到 2 秒是平衡点。4.4 存储与权限Android 10 以上的分区存储现象保存路径 JSON 到外部存储时报Permission denied。原因Android 10 引入了分区存储WRITE_EXTERNAL_STORAGE不再对Environment.getExternalStorageDirectory()生效。解决把数据存到getExternalFilesDir()或者直接用 SQLite 存内部数据库不需要任何存储权限。这个项目如果只存 SQLite完全可以去掉存储权限。5. 进阶技巧用模拟轨迹验证路径绘制与数据回放真机跑一次只能测一条路线调试路径绘制逻辑时效率很低。我一般会写一个模拟定位的开关用代码生成一条预设轨迹直接喂给onLocationChanged。这样不用出门就能验证折线绘制、速度计算和履历存储是否正常。// 模拟轨迹在测试模式下每 2 秒生成一个点 private void startMockLocation() { final Handler handler new Handler(); final double[][] mockPoints { {39.9042, 116.4074}, {39.9045, 116.4080}, {39.9049, 116.4086}, {39.9053, 116.4092} }; final int[] index {0}; handler.postDelayed(new Runnable() { Override public void run() { if (index[0] mockPoints.length) return; AMapLocation mock new AMapLocation(mock); mock.setLatitude(mockPoints[index[0]][0]); mock.setLongitude(mockPoints[index[0]][1]); mock.setSpeed(3.0f); // 固定 3 m/s约 10.8 km/h mock.setErrorCode(0); onLocationChanged(mock); index[0]; handler.postDelayed(this, 2000); } }, 2000); }这段代码的关键是构造一个AMapLocation对象并手动设置errorCode为 0否则onLocationChanged里的判断会直接 return。setSpeed(3.0f)模拟的是跑步速度你可以改成 0.5 测走路改成 8.0 测骑行。用这个方式十分钟就能把路径绘制、速度显示、数据入库三条链路全跑一遍。验证数据回放时从 SQLite 里读出一条记录的path_json反序列化成ListLatLng再aMap.addPolyline画出来。如果画出来的线和跑步时看到的一致说明存储和读取都没丢点。我习惯在每次改完定位逻辑后先用模拟轨迹跑三遍再拿真机出门跑一次。从那以后我每次接定位相关的需求都强制走一遍「模拟轨迹 → 真机短距离 → 真机长距离」的流程能省下大量在户外反复调试的时间。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

智能体技能工程化:可复用、可编排、可验证的Agent Skills设计实践

智能体技能工程化:可复用、可编排、可验证的Agent Skills设计实践

1. 项目概述:从“agent-skills”这个词组看懂当前智能体开发的真实水位“agent-skills”不是某个具体工具、框架或开源库的官方名称,而是一个高度凝练的行业术语组合——它直指当前AI工程落地中最关键、也最容易被忽视的一环:智能体&#xff…

2026/10/13 17:13:14 阅读更多 →
Android Studio校园图书管理系统课设:SQLite本地数据库实现与答辩避坑指南

Android Studio校园图书管理系统课设:SQLite本地数据库实现与答辩避坑指南

简介:这是一份面向高校学生与Android初学者的校园图书管理系统课程设计完整源码,基于Android Studio开发,可作为移动应用开发课程的满分课设参考。项目围绕用户管理、图书查询、虚拟货币充值、评论评分等核心业务展开,覆盖Activit…

2026/10/13 17:13:14 阅读更多 →
从零重构微信投票系统:数据模型、防刷体系与高并发架构实战

从零重构微信投票系统:数据模型、防刷体系与高并发架构实战

做投票系统这事,听起来好像很简单:一个页面,几个选项,点一下提交,完事。可真要把一套投票系统做到既能扛住公众号几万人同时参与、又能灵活切换多种投票玩法、还得在活动期间顶住各种恶意刷票冲击的时候,你…

2026/10/13 17:13:14 阅读更多 →

最新新闻

弗洛伊德解梦:噩梦为何也是潜意识的愿望满足?

弗洛伊德解梦:噩梦为何也是潜意识的愿望满足?

你有没有做过这种梦:明天就要交一份至关重要的方案,梦里你却发现自己连文件都找不到,或者更离谱,直接站在空无一人的考场里,试卷上的字全在飘。惊醒之后心跳半天才缓过来,第一反应往往是“这梦太丧了”。但…

2026/10/13 17:56:30 阅读更多 →
Codex 半年实战复盘:省 Token 技巧与高阶玩法全解析

Codex 半年实战复盘:省 Token 技巧与高阶玩法全解析

1. 半年迭代复盘:Codex 到底更新了哪些关键能力从去年底到现在,Codex 这个命令行编程智能体的更新节奏明显加快,几乎每隔两三周就会推一次有感知的变化。我自己的主力工作流已经全面切到 Codex 上,半年下来踩了不少坑,…

2026/10/13 17:56:30 阅读更多 →
t3code 深度解析:轻量级代码工具的设计思路与实操指南

t3code 深度解析:轻量级代码工具的设计思路与实操指南

1. 从“t3code”这个标题说起:它到底是什么,能解决什么问题第一次看到“t3code”这个标题,很多人会一头雾水。它不像“Python爬虫实战”那样直白,也不像“家庭咖啡烘焙指南”那样有明确场景。但恰恰是这种模糊性,给了我…

2026/10/13 17:56:30 阅读更多 →
Delphi老项目救星:KonopkaControls控件包安装与实战避坑指南

Delphi老项目救星:KonopkaControls控件包安装与实战避坑指南

简介:面向Delphi 13.1开发者的KonopkaControls 8.0.1控件包,是扩展VCL标准组件库的第三方界面控件集合,能有效补充原生控件在界面表现与交互能力上的不足,适合桌面应用开发及快速原型构建。压缩包共2000个文件,包含112…

2026/10/13 17:56:30 阅读更多 →
内容质量检查流水线:从错别字到失效链接的全面校验

内容质量检查流水线:从错别字到失效链接的全面校验

前阵子我在整理自己博客后台时,翻到一篇半年前阅读量还不错的旧文,发现里面躺着一个前期完全没注意到的错别字,还有一个早就失效的外部链接。那种感觉很难形容,就像精心布置的客厅里,墙角偏偏有一块没擦干净的污渍。也…

2026/10/13 17:56:30 阅读更多 →
Service层命名规范:从见名知意到代码可维护性

Service层命名规范:从见名知意到代码可维护性

接手一个业务系统,我最怕看到的不是复杂算法,而是那种一打开就让人头晕的 Service 实现类。2000 行起步,方法名字从 process 到 handle 再到 doSomething,翻遍整个类也猜不出某个方法是干嘛的。命名这种事,看起来不影响…

2026/10/13 17:55:28 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →