更新记录
1.0.0(2026-03-12)
- Android:新增
strategy引擎策略参数,支持auto、preferHealthConnect、preferSensor、healthConnectOnly、sensorOnly - Android:查询、授权、实时监听统一改为 resolver 路由,
getTodayStepCount()现在会按授权状态在Health Connect和Sensor之间回退 - Android:将插件
minSdkVersion提升到 26,以满足androidx.health.connect:connect-client的构建要求并修复云打包失败 - Android / iOS:结果与授权对象新增
resolvedEngine、requestedStrategy、availableEngines字段 - Android / iOS / Harmony:新增
getAvailableEngines()能力探测接口 - Android:新增
ForegroundService持有TYPE_STEP_COUNTER监听,支持应用退到后台后继续采集并持久化今日步数 - Android:监听通知改为前台服务模型,
task.stop()会同步停止服务并移除通知 - Android:补充
FOREGROUND_SERVICE、FOREGROUND_SERVICE_HEALTH与服务组件声明,并更新插件权限文档 - Android:补充
POST_NOTIFICATIONS权限声明、通知状态查询与通知设置入口,requestAuthorization()现会顺序请求步数权限与通知权限
平台兼容性
uni-app(4.87)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| √ | √ | - | - | - | - | √ | √ | - |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| - | - | - | - | - | - | - | - | - | - | - | - |
uni-app x(4.87)
| Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|
| - | - | √ | √ | - | - |
hans-step-counter
hans-step-counter 是一个同时支持 uni-app 与 uni-app x 的步数插件,提供 Android 和 iOS 的步数授权、今日步数查询与实时监听能力。
适用范围
| 项目 | 说明 |
|---|---|
| 框架 | uni-app / uni-app x |
| HBuilderX | ^3.6.8 |
| Android | 8.0+ (API 26+) |
| iOS | 12.0+ |
| Harmony | 1.0.0 暂不支持 |
能力列表
- 检测设备是否支持步数能力
- 获取当前可用引擎和授权状态
- 请求步数相关权限
- 查询今日步数
- 监听步数变化
- 打开系统设置页
- 打开 Android 通知设置页
- 打开或关闭插件日志
引入方式
经典 uni-app 的 .vue 页面和 uni-app x 的 .uvue 页面都可以按下面方式引入:
import {
isStepCounterSupported,
getAvailableEngines,
getAuthorizationStatus,
requestAuthorization,
getTodayStepCount,
startStepCountUpdates,
openAppSettings,
openNotificationSettings,
setLogEnabled,
isLogEnabled,
RequestAuthorizationOptions,
GetTodayStepCountOptions,
StartStepCountUpdatesOptions,
StepCounterAuthorizationResult,
StepCountResult,
StepCountChange,
StepCounterFail,
} from '@/uni_modules/hans-step-counter'
快速开始
1. 检查支持情况
const supported = isStepCounterSupported()
const engines = getAvailableEngines()
const auth = getAuthorizationStatus()
console.log('supported', supported)
console.log('engines', engines)
console.log('auth', auth.status)
getAvailableEngines() 返回值:
- Android:
['healthConnect']、['sensor']或['healthConnect', 'sensor'] - iOS:
['pedometer'] - Harmony:
[]
2. 请求授权
const authOptions: RequestAuthorizationOptions = {
strategy: 'preferSensor',
success: (res: StepCounterAuthorizationResult) => {
console.log('auth success', res.status, res.resolvedEngine, res.availableEngines)
},
fail: (err: StepCounterFail) => {
console.error('auth fail', err.errCode, err.errMsg)
},
}
requestAuthorization(authOptions)
3. 查询今日步数
const stepOptions: GetTodayStepCountOptions = {
strategy: 'preferHealthConnect',
success: (res: StepCountResult) => {
console.log('today steps', res.steps)
console.log('engine', res.resolvedEngine)
console.log('accurate', res.isAccurate)
console.log('trackedFromTime', res.trackedFromTime)
console.log('note', res.note)
},
fail: (err: StepCounterFail) => {
console.error('query fail', err.errCode, err.errMsg)
},
}
getTodayStepCount(stepOptions)
4. 监听步数变化
const updateOptions: StartStepCountUpdatesOptions = {
strategy: 'sensorOnly',
emitCurrent: true,
onChange: (res: StepCountChange) => {
console.log('total', res.totalSteps)
console.log('delta', res.deltaSteps)
console.log('engine', res.resolvedEngine)
},
fail: (err: StepCounterFail) => {
console.error('listen fail', err.errCode, err.errMsg)
},
}
const task = startStepCountUpdates(updateOptions)
task.stop()
5. 打开设置和日志
setLogEnabled(true)
console.log('log enabled', isLogEnabled())
openAppSettings()
openNotificationSettings()
openNotificationSettings() 主要用于 Android 前台服务通知不可见或被用户关闭时的引导。
API 概览
setLogEnabled(enabled: boolean): void
isLogEnabled(): boolean
isStepCounterSupported(): boolean
getAvailableEngines(): Array<StepCounterEngine>
getAuthorizationStatus(): StepCounterAuthorizationResult
requestAuthorization(options: RequestAuthorizationOptions): void
getTodayStepCount(options: GetTodayStepCountOptions): void
startStepCountUpdates(options: StartStepCountUpdatesOptions): StepCounterTask
openAppSettings(): void
openNotificationSettings(): void
类型定义
以下类型以 utssdk/interface.uts 为准。
字面量类型
type StepCounterPlatform = 'android' | 'ios' | 'harmony'
type StepCounterSource = 'sensor' | 'healthConnect' | 'pedometer' | 'stub'
type StepCounterEngine = 'sensor' | 'healthConnect' | 'pedometer'
type StepCounterStrategy =
| 'auto'
| 'preferHealthConnect'
| 'preferSensor'
| 'healthConnectOnly'
| 'sensorOnly'
type StepCounterAuthorizationStatus =
| 'authorized'
| 'denied'
| 'notDetermined'
| 'restricted'
| 'unsupported'
type StepCounterErrorCode =
| 9011001
| 9011002
| 9011003
| 9011004
| 9011005
| 9011006
| 9011007
| 9011008
| 9011009
| 9011010
Options 类型
type RequestAuthorizationOptions = {
strategy?: StepCounterStrategy | null
success?: (res: StepCounterAuthorizationResult) => void
fail?: (err: StepCounterFail) => void
complete?: (res: any) => void
}
type GetTodayStepCountOptions = {
strategy?: StepCounterStrategy | null
success?: (res: StepCountResult) => void
fail?: (err: StepCounterFail) => void
complete?: (res: any) => void
}
type StartStepCountUpdatesOptions = {
strategy?: StepCounterStrategy | null
emitCurrent?: boolean
onChange: (res: StepCountChange) => void
fail?: (err: StepCounterFail) => void
}
返回类型
interface StepCounterTask {
stop(): void
}
interface StepCounterFail extends IUniError {
errCode: StepCounterErrorCode
}
type StepCounterAuthorizationResult = {
status: StepCounterAuthorizationStatus
platform: StepCounterPlatform
isSupported: boolean
resolvedEngine: StepCounterEngine | null
requestedStrategy: StepCounterStrategy | null
availableEngines: Array<StepCounterEngine>
permissionRequired: boolean
permissionDeclared: boolean
doNotAskAgain: boolean | null
notificationPermissionRequired: boolean
notificationPermissionDeclared: boolean
notificationStatus: StepCounterAuthorizationStatus
notificationDoNotAskAgain: boolean | null
notificationsEnabled: boolean
notificationChannelEnabled: boolean | null
}
type StepCountResult = {
steps: number
startTime: number
endTime: number
platform: StepCounterPlatform
source: StepCounterSource
resolvedEngine: StepCounterEngine
requestedStrategy: StepCounterStrategy | null
distance: number | null
floorsAscended: number | null
floorsDescended: number | null
trackedFromTime: number | null
isAccurate: boolean
note: string | null
}
type StepCountChange = {
totalSteps: number
deltaSteps: number
timestamp: number
platform: StepCounterPlatform
source: StepCounterSource
resolvedEngine: StepCounterEngine
requestedStrategy: StepCounterStrategy | null
trackedFromTime: number | null
isAccurate: boolean
note: string | null
}
时间和可空字段约定
startTime、endTime、timestamp、trackedFromTime都是 Unix 时间戳毫秒值trackedFromTime == null表示插件无法给出可信起点requestedStrategy == null只会出现在少量内部兜底场景,业务侧通常会拿到具体值或autodistance、floorsAscended、floorsDescended目前主要由 iOSCMPedometer提供,Android 侧通常为null
API 说明
setLogEnabled(enabled)
setLogEnabled(enabled: boolean): void
- 入参
enabled:boolean true开启插件日志,false关闭
isLogEnabled()
isLogEnabled(): boolean
- 返回当前日志开关状态
isStepCounterSupported()
isStepCounterSupported(): boolean
- 仅表示设备和当前平台是否存在可用步数能力
- 不代表权限已经授权
getAvailableEngines()
getAvailableEngines(): Array<StepCounterEngine>
- 返回当前设备可用引擎列表
- Android 可能返回
sensor、healthConnect或两者都有 - iOS 仅可能返回
pedometer
getAuthorizationStatus()
getAuthorizationStatus(): StepCounterAuthorizationResult
- 返回当前默认策略下的授权状态快照
- 不会主动弹权限框
- Android 返回值里会同时带上通知权限和通知渠道状态
requestAuthorization(options)
requestAuthorization(options: RequestAuthorizationOptions): void
options 字段:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
strategy |
StepCounterStrategy \| null |
否 | 选择授权目标引擎,未传时按 auto |
success |
(res: StepCounterAuthorizationResult) => void |
否 | 授权流程成功结束或返回当前状态时回调 |
fail |
(err: StepCounterFail) => void |
否 | 授权流程异常时回调 |
complete |
(res: any) => void |
否 | 无论成功或失败都会回调 |
说明:
- Android
auto默认优先申请sensor - iOS 始终走
pedometer,strategy仅保留在返回值里 - Harmony 当前会直接走
success,返回status: 'unsupported' complete成功时收到StepCounterAuthorizationResult,失败时收到StepCounterFail
调用示例:
requestAuthorization({
strategy: 'preferSensor',
success: (res: StepCounterAuthorizationResult) => {
console.log(res.status)
console.log(res.resolvedEngine)
console.log(res.notificationStatus)
},
fail: (err: StepCounterFail) => {
console.error(err.errCode, err.errMsg)
},
complete: (res: any) => {
console.log('complete', res)
},
})
getTodayStepCount(options)
getTodayStepCount(options: GetTodayStepCountOptions): void
options 字段:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
strategy |
StepCounterStrategy \| null |
否 | 查询时的引擎策略,未传时按 auto |
success |
(res: StepCountResult) => void |
否 | 查询成功回调 |
fail |
(err: StepCounterFail) => void |
否 | 查询失败回调 |
complete |
(res: any) => void |
否 | 无论成功或失败都会回调 |
说明:
- Android
auto默认优先使用healthConnect,不可用时回退sensor - iOS 始终使用
pedometer - Harmony 当前直接失败,错误码为
9011001 complete成功时收到StepCountResult,失败时收到StepCounterFail
startStepCountUpdates(options)
startStepCountUpdates(options: StartStepCountUpdatesOptions): StepCounterTask
options 字段:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
strategy |
StepCounterStrategy \| null |
否 | 监听时的引擎策略,未传时按 auto |
emitCurrent |
boolean |
否 | 是否在启动后立即回调一次当前值,默认 true |
onChange |
(res: StepCountChange) => void |
是 | 步数变化回调 |
fail |
(err: StepCounterFail) => void |
否 | 启动失败或监听过程出错时回调 |
说明:
- 返回值始终是
StepCounterTask,不需要监听时调用task.stop() - Android 实时监听仅支持
sensor - iOS 使用
CMPedometer实时更新 - Harmony 当前直接触发
fail - 如果指定
healthConnectOnly去调用实时监听,Android 会因为该引擎不支持实时更新而失败
openAppSettings()
openAppSettings(): void
- 打开当前应用系统设置页
- 适用于权限被永久拒绝后的引导
openNotificationSettings()
openNotificationSettings(): void
- Android:打开通知设置页
- iOS:当前实现会回退到应用设置页
- 主要用于 Android 前台服务通知被关闭时的引导
Strategy 说明
以下接口支持传入 strategy:
requestAuthorization()getTodayStepCount()startStepCountUpdates()
可选值:
autopreferHealthConnectpreferSensorhealthConnectOnlysensorOnly
Android 下默认 auto 行为如下:
requestAuthorization():优先申请sensorgetTodayStepCount():优先使用healthConnect,不可用时回退sensorstartStepCountUpdates():优先使用sensor
接入建议:
- 只关心查询今日总步数:优先
auto或preferHealthConnect - 需要实时监听和后台持续累计:优先
auto或preferSensor - 明确只接受某一种引擎:使用
healthConnectOnly或sensorOnly
返回结果字段说明
StepCounterAuthorizationResult
| 字段 | 类型 | 说明 |
|---|---|---|
status |
StepCounterAuthorizationStatus |
当前授权状态 |
platform |
StepCounterPlatform |
当前平台 |
isSupported |
boolean |
当前平台和设备是否支持 |
resolvedEngine |
StepCounterEngine \| null |
当前策略最终命中的引擎 |
requestedStrategy |
StepCounterStrategy \| null |
本次使用的策略 |
availableEngines |
Array<StepCounterEngine> |
当前设备可用引擎列表 |
permissionRequired |
boolean |
当前引擎是否需要权限 |
permissionDeclared |
boolean |
原生权限是否已在工程中声明 |
doNotAskAgain |
boolean \| null |
Android 是否更适合直接去系统设置 |
notificationPermissionRequired |
boolean |
Android 通知权限是否需要单独申请 |
notificationPermissionDeclared |
boolean |
Android 是否声明了通知权限 |
notificationStatus |
StepCounterAuthorizationStatus |
Android 通知权限状态;其他平台通常为 unsupported |
notificationDoNotAskAgain |
boolean \| null |
Android 通知权限是否被用户永久拒绝 |
notificationsEnabled |
boolean |
Android 系统通知总开关是否打开 |
notificationChannelEnabled |
boolean \| null |
Android 前台服务通知渠道是否启用 |
StepCountResult
| 字段 | 类型 | 说明 |
|---|---|---|
steps |
number |
今日累计步数 |
startTime |
number |
本次统计区间起点,毫秒时间戳 |
endTime |
number |
本次统计区间终点,毫秒时间戳 |
platform |
StepCounterPlatform |
当前平台 |
source |
StepCounterSource |
数据来源 |
resolvedEngine |
StepCounterEngine |
实际使用的引擎 |
requestedStrategy |
StepCounterStrategy \| null |
本次查询使用的策略 |
distance |
number \| null |
距离,iOS 下通常是米 |
floorsAscended |
number \| null |
上楼层数,iOS 可用 |
floorsDescended |
number \| null |
下楼层数,iOS 可用 |
trackedFromTime |
number \| null |
当前结果可信的起始时间 |
isAccurate |
boolean |
是否可视为完整统计 |
note |
string \| null |
补充说明,建议只用于展示或日志 |
StepCountChange
| 字段 | 类型 | 说明 |
|---|---|---|
totalSteps |
number |
当前累计总步数 |
deltaSteps |
number |
相对上一次回调新增的步数 |
timestamp |
number |
本次事件时间,毫秒时间戳 |
platform |
StepCounterPlatform |
当前平台 |
source |
StepCounterSource |
数据来源 |
resolvedEngine |
StepCounterEngine |
实际使用的引擎 |
requestedStrategy |
StepCounterStrategy \| null |
本次监听使用的策略 |
trackedFromTime |
number \| null |
当前累计可信的起始时间 |
isAccurate |
boolean |
是否可视为完整统计 |
note |
string \| null |
补充说明,建议只用于展示或日志 |
精度字段使用建议
以下场景下,步数结果可能不是完整的全天统计:
- 当天较晚才第一次启动插件
- 跨午夜期间没有持续观测
- 设备重启或传感器累计值被系统重置
建议页面按以下方式处理:
isAccurate == false:给用户展示“统计可能不完整”的提示trackedFromTime != null:可提示“当前统计从某个时间点开始”note != null:只用于展示和日志,不建议业务逻辑依赖文案内容
Android 使用说明
权限
插件已声明以下 Android 权限:
android.permission.ACTIVITY_RECOGNITIONandroid.permission.POST_NOTIFICATIONSandroid.permission.FOREGROUND_SERVICEandroid.permission.FOREGROUND_SERVICE_HEALTHandroid.permission.health.READ_STEPS
说明:
sensor路径会使用步数传感器和前台服务healthConnect路径会拉起 Health Connect 授权页- Android 13+ 在
sensor路径下会顺序请求活动识别权限和通知权限 - 如果业务指定
healthConnectOnly或优先使用healthConnect,请先确认设备已安装并可用 Health Connect,否则可能返回9011009或9011010
后台监听
- Android 下调用
startStepCountUpdates()会启动前台服务并显示持续通知 task.stop()会停止监听并移除通知- 页面退到后台后,页面回调可能暂停,但原生层仍会继续累计和持久化
- 如果有多个页面或多个消费者,建议在应用层只维护一个原生监听任务,再自行分发事件
iOS 使用说明
- 插件已声明
NSMotionUsageDescription - 首次读取步数或启动监听前,应先调用
requestAuthorization() - iOS 使用
CMPedometer提供查询和实时步数更新能力 distance、floorsAscended、floorsDescended只有系统提供时才会返回
Harmony 说明
- 当前版本仅提供占位实现,不支持真实步数能力
isStepCounterSupported()恒为falserequestAuthorization()会返回status: 'unsupported'getTodayStepCount()和startStepCountUpdates()会以9011001失败
错误码
| 错误码 | 含义 |
|---|---|
9011001 |
当前平台不支持 |
9011002 |
当前设备没有可用步数引擎,或当前操作没有可用实时监听引擎 |
9011003 |
Android 活动识别权限未授权 |
9011004 |
iOS 运动与健身权限不可用、未授权或受限 |
9011005 |
传入参数无效 |
9011006 |
启动步数监听失败 |
9011007 |
查询步数失败 |
9011008 |
插件内部错误 |
9011009 |
Health Connect 未安装或需要升级 |
9011010 |
Health Connect 未授权或同步不可用 |

收藏人数:
购买普通授权版(
试用
赞赏(0)
下载 260
赞赏 0
下载 11405630
赞赏 1873
赞赏
京公网安备:11010802035340号