概述
App Inventor 2可以通过以下方式实现计步和距离测量:
| 方案 | 组件 | 精度 | 说明 |
|---|---|---|---|
| 计步器传感器 | Pedometer扩展 | 高 | 硬件计步器 |
| 加速度分析 | AccelerometerSensor | 中 | 软件算法 |
| GPS距离 | LocationSensor | 户外高 | 基于GPS轨迹 |
方案一:计步器传感器
原理
现代Android手机内置硬件计步器传感器(TYPE_STEP_COUNTER),精度高且功耗低。
使用扩展
需要计步器扩展(如StepCounter扩展)。
当 Screen1.初始化
设 今日步数 = TinyDB1.获取值("today_steps", 0)
设 今日日期 = Clock1.格式化日期时间(Clock1.当前时间(), "yyyy-MM-dd")
设 保存日期 = TinyDB1.获取值("today_date", "")
如果 保存日期 ≠ 今日日期
' 新的一天,重置步数
设 今日步数 = 0
调用 TinyDB1.存储值("today_date", 今日日期)
调用 TinyDB1.存储值("today_steps", 0)
调用 StepCounter1.开始()
标签_步数.文本 = 今日步数
当 StepCounter1.步数变化(步数)
设 今日步数 = 步数
标签_步数.文本 = 步数 & " 步"
调用 TinyDB1.存储值("today_steps", 步数)
' 计算距离(估算)
设 步幅 = 0.7 ' 平均步幅0.7米
设 距离米 = 步数 * 步幅
如果 距离米 < 1000
标签_距离.文本 = 数学.保留小数(距离米, 0) & " 米"
否则
标签_距离.文本 = 数学.保留小数(距离米 / 1000, 2) & " 公里"
' 计算卡路里(估算)
设 体重KG = 70 ' 假设体重
设 卡路里 = 步数 * 0.04 * 体重KG / 70 ' 粗略估算
标签_卡路里.文本 = 数学.保留小数(卡路里, 1) & " 千卡"
步数距离单位说明
计步传感器返回的步数是计数(步),distance是传感器估算的距离(如果传感器支持的话)。需要换算:
- 1步 ≈ 0.6-0.8米(因人而异)
- 1000步 ≈ 600-800米
- 10000步 ≈ 6-8公里
方案二:加速度计检测步数
没有硬件计步器时,用加速度传感器算法检测:
原理
走路时加速度有周期性波动。检测加速度的模值超过阈值即为一步。
设 步数 = 0
设 上次峰值时间 = 0
设 最小步间隔 = 250 ' 毫秒,两步之间最小间隔
设 加速度阈值 = 12.5 ' 检测阈值
当 AccelerometerSensor1.加速度改变(xAccel, yAccel, zAccel)
设 加速度模 = 数学.平方根(xAccel*xAccel + yAccel*yAccel + zAccel*zAccel)
设 当前时间 = Clock1.获取毫秒数(Clock1.当前时间())
如果 加速度模 > 加速度阈值
设 时间差 = 当前时间 - 上次峰值时间
如果 时间差 > 最小步间隔
设 步数 = 步数 + 1
设 上次峰值时间 = 当前时间
标签_步数.文本 = 步数 & " 步"
优化算法(带滤波)
设 滤波值 = 9.8 ' 初始化为重力加速度
设 滤波系数 = 0.1
设 步数 = 0
当 AccelerometerSensor1.加速度改变(xAccel, yAccel, zAccel)
设 原始模 = 数学.平方根(xAccel^2 + yAccel^2 + zAccel^2)
' 低通滤波
设 滤波值 = 滤波值 + 滤波系数 * (原始模 - 滤波值)
' 检测峰值
设 偏差 = 滤波值 - 9.8 ' 去除重力
如果 偏差 > 2.5 ' 阈值
设 当前时间 = Clock1.获取毫秒数(Clock1.当前时间())
如果 (当前时间 - 上次峰值时间) > 300
设 步数 = 步数 + 1
设 上次峰值时间 = 当前时间
方案三:GPS距离测量
已有文档
sensors.md 介绍了LocationSensor基本用法,map_geofence.md 介绍了Haversine距离计算。此处补充轨迹记录和总距离计算。
记录GPS轨迹计算总距离
设 轨迹点 = 创建空列表
设 总距离 = 0
当 LocationSensor1.位置改变(纬度, 经度, 海拔, 速度)
设 新点 = 创建字典("lat" → 纬度, "lng" → 经度, "time" → Clock1.获取毫秒数(Clock1.当前时间()))
如果 列表长度(轨迹点) > 0
设 上一点 = 列表第(列表长度(轨迹点))项(轨迹点)
设 段距离 = Haversine距离(
从字典 上一点 获取 "lat", 从字典 上一点 获取 "lng",
纬度, 经度
)
设 总距离 = 总距离 + 段距离
设 轨迹点 = 添加列表项(轨迹点, 新点)
' 显示
如果 总距离 < 1000
标签_总距离.文本 = 数学.保留小数(总距离, 0) & " 米"
否则
标签_总距离.文本 = 数学.保留小数(总距离 / 1000, 2) & " 公里"
标签_轨迹点数.文本 = 列表长度(轨迹点) & " 个轨迹点"
标签_当前速度.文本 = 数学.保留小数(速度 * 3.6, 1) & " km/h" ' m/s → km/h
实战案例:运动记录App
功能
- 实时计步
- GPS轨迹记录
- 运动距离/时间/卡路里
- 运动历史记录
界面设计
Screen_Run
├── 标签_步数
├── 标签_距离
├── 标签_时间
├── 标签_卡路里
├── 标签_速度
├── 按钮_开始/暂停
├── 按钮_结束
├── Map1(轨迹地图)
├── LocationSensor1
├── StepCounter1
├── Clock1(计时)
└── TinyDB1(存储记录)
核心积木块
设 运动中 = false
设 开始时间 = 0
设 总步数 = 0
设 总距离 = 0
设 轨迹点 = 创建空列表
当 按钮_开始.被点击
设 运动中 = true
设 开始时间 = Clock1.获取毫秒数(Clock1.当前时间())
设 LocationSensor1.启用 = true
调用 StepCounter1.开始()
设 Clock_计时.计时器间隔 = 1000
设 Clock_计时.启用计时器 = true
设 按钮_开始.文本 = "暂停"
当 Clock_计时.计时
如果 运动中
设 已用毫秒 = Clock1.获取毫秒数(Clock1.当前时间()) - 开始时间
设 分钟 = 数学.向下取整(已用毫秒 / 60000)
设 秒 = 数学.向下取整((已用毫秒 模 60000) / 1000)
标签_时间.文本 = 文本格式("%02d:%02d", 分钟, 秒)
当 按钮_结束.被点击
设 运动中 = false
设 LocationSensor1.启用 = false
设 Clock_计时.启用计时器 = false
' 保存运动记录
设 记录 = 创建字典(
"date" → Clock1.格式化日期时间(Clock1.当前时间(), "yyyy-MM-dd HH:mm"),
"steps" → 总步数,
"distance" → 数学.保留小数(总距离, 0),
"duration" → 标签_时间.文本,
"calories" → 标签_卡路里.文本
)
设 历史记录 = TinyDB1.获取值("run_history", 创建空列表)
设 历史记录 = 添加列表项(历史记录, 记录)
调用 TinyDB1.存储值("run_history", 历史记录)
常见问题
Q1: 计步传感器distance是什么单位?
如果传感器返回distance值,通常是米。但很多Android设备的计步传感器不提供distance,只提供步数(steps)。需要用 步数 × 步幅 估算距离。
Q2: 加速度计计步不准确?
软件算法受以下影响:
- 手机放置位置(口袋/手中/桌上)
- 走路速度和姿势
- 其他运动干扰(骑车、颠簸)
建议使用硬件计步器扩展更准确。
Q3: GPS轨迹记录耗电?
持续GPS定位很耗电。优化:
- 增大
DistanceInterval(如5米才更新一次) - 降低更新频率
- 使用
TimerEnabled间歇性获取位置
总结
| 方案 | 精度 | 耗电 | 适用 |
|---|---|---|---|
| 硬件计步器 | ⭐⭐⭐⭐ | 低 | 计步 |
| 加速度算法 | ⭐⭐ | 低 | 无硬件计步器时 |
| GPS轨迹 | ⭐⭐⭐⭐ | 高 | 户外运动距离 |
版权声明:MIT App Inventor 官方文档采用 CC BY-SA 4.0 授权,本文档由 ai2claw 🐝 整理。
扫码添加客服咨询