web-step-counter-pro 1.0.1 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +2 -4
  2. package/step-counter.js +67 -11
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "web-step-counter-pro",
3
- "version": "1.0.1",
3
+ "version": "1.0.4",
4
4
  "description": "A professional-grade web step counting library with advanced anti-cheat mechanisms (GPS, Gyroscope, Rhythm Analysis).",
5
5
  "main": "step-counter.js",
6
6
  "type": "module",
@@ -23,7 +23,5 @@
23
23
  "README.md",
24
24
  "package.json"
25
25
  ],
26
- "dependencies": {
27
-
28
- }
26
+ "dependencies": {}
29
27
  }
package/step-counter.js CHANGED
@@ -49,6 +49,7 @@ export class WebStepCounter {
49
49
  gpsAccuracyLimit: 20,
50
50
  maxSpeed: 2.8,
51
51
  debug: false,
52
+ autoPauseOnBackground: true, // 新增: Capacitor 环境下切后台自动暂停传感器
52
53
  onStep: null,
53
54
  onStatus: null,
54
55
  onSensorData: null,
@@ -58,6 +59,7 @@ export class WebStepCounter {
58
59
  // 内部状态
59
60
  this.stepCount = 0;
60
61
  this.isTracking = false;
62
+ this.isPausedByBackground = false; // 新增: 标记是否因后台而暂停
61
63
  this.candidateSteps = 0;
62
64
  this.lastStepTime = 0;
63
65
  this.lastCandidateStepTime = 0;
@@ -76,6 +78,9 @@ export class WebStepCounter {
76
78
 
77
79
  this.orientationData = { alpha: 0, beta: 0, gamma: 0 };
78
80
 
81
+ // 节流控制
82
+ this._lastUiUpdate = 0;
83
+
79
84
  this.handleMotion = this.handleMotion.bind(this);
80
85
  this.handleOrientation = this.handleOrientation.bind(this);
81
86
  this.handleGeolocation = this.handleGeolocation.bind(this);
@@ -84,13 +89,21 @@ export class WebStepCounter {
84
89
  async start() {
85
90
  if (this.isTracking) return;
86
91
 
87
- if (location.protocol !== 'https:' && location.hostname !== 'localhost' && location.hostname !== '127.0.0.1') {
92
+ const isCapacitor = !!window.Capacitor;
93
+
94
+ // 1. HTTPS 检查 (Capacitor 环境豁免)
95
+ if (!isCapacitor && location.protocol !== 'https:' && location.hostname !== 'localhost' && location.hostname !== '127.0.0.1') {
88
96
  this._reportStatus("必须使用 HTTPS 协议", WebStepCounter.StatusType.ERROR, WebStepCounter.StatusCode.HTTPS_REQUIRED);
89
97
  return false;
90
98
  }
91
99
 
92
100
  this._reportStatus("正在请求传感器权限...", WebStepCounter.StatusType.INFO);
93
101
 
102
+ // Capacitor 优化: 绑定生命周期
103
+ if (isCapacitor && this.config.autoPauseOnBackground) {
104
+ this._initCapacitorLifecycle();
105
+ }
106
+
94
107
  const permissionGranted = await this._requestPermissions();
95
108
  if (!permissionGranted) return false;
96
109
 
@@ -109,13 +122,19 @@ export class WebStepCounter {
109
122
 
110
123
  stop() {
111
124
  this.isTracking = false;
112
- window.removeEventListener('devicemotion', this.handleMotion);
113
- window.removeEventListener('deviceorientation', this.handleOrientation);
114
- window.removeEventListener('deviceorientationabsolute', this.handleOrientation);
125
+ this._removeSensors();
115
126
 
116
127
  if (this.watchId) {
117
128
  navigator.geolocation.clearWatch(this.watchId);
129
+ this.watchId = null;
118
130
  }
131
+
132
+ // 清理 Capacitor 监听
133
+ if (this.appListener) {
134
+ this.appListener.remove();
135
+ this.appListener = null;
136
+ }
137
+
119
138
  this._reportStatus("已停止", WebStepCounter.StatusType.INFO);
120
139
  }
121
140
 
@@ -147,6 +166,49 @@ export class WebStepCounter {
147
166
 
148
167
  // --- Internal ---
149
168
 
169
+ // Capacitor 生命周期处理
170
+ _initCapacitorLifecycle() {
171
+ if (!window.Capacitor || !window.Capacitor.Plugins || !window.Capacitor.Plugins.App) return;
172
+
173
+ const App = window.Capacitor.Plugins.App;
174
+
175
+ // 监听 App 状态变化
176
+ this.appListener = App.addListener('appStateChange', ({ isActive }) => {
177
+ if (!this.isTracking) return;
178
+
179
+ if (!isActive) {
180
+ // 切到后台: 暂停传感器以省电,并防止 iOS 冻结导致的异常数据
181
+ this._reportStatus("App 进入后台,暂停计步", WebStepCounter.StatusType.INFO);
182
+ this._removeSensors();
183
+ this.isPausedByBackground = true;
184
+ } else {
185
+ // 切回前台: 恢复
186
+ if (this.isPausedByBackground) {
187
+ this._reportStatus("App 回到前台,恢复计步", WebStepCounter.StatusType.INFO);
188
+ this._addSensors();
189
+ this.isPausedByBackground = false;
190
+ }
191
+ }
192
+ });
193
+ }
194
+
195
+ _addSensors() {
196
+ window.addEventListener('devicemotion', this.handleMotion);
197
+ // 重新检查环境支持情况来决定添加哪个 Orientation 事件
198
+ if (window.DeviceOrientationEvent) {
199
+ window.addEventListener('deviceorientation', this.handleOrientation);
200
+ }
201
+ if ('ondeviceorientationabsolute' in window) {
202
+ window.addEventListener('deviceorientationabsolute', this.handleOrientation);
203
+ }
204
+ }
205
+
206
+ _removeSensors() {
207
+ window.removeEventListener('devicemotion', this.handleMotion);
208
+ window.removeEventListener('deviceorientation', this.handleOrientation);
209
+ window.removeEventListener('deviceorientationabsolute', this.handleOrientation);
210
+ }
211
+
150
212
  async _requestPermissions() {
151
213
  if (typeof DeviceMotionEvent !== 'undefined' && typeof DeviceMotionEvent.requestPermission === 'function') {
152
214
  try {
@@ -175,13 +237,7 @@ export class WebStepCounter {
175
237
  return false;
176
238
  }
177
239
  } else {
178
- window.addEventListener('devicemotion', this.handleMotion);
179
- if (window.DeviceOrientationEvent) {
180
- window.addEventListener('deviceorientation', this.handleOrientation);
181
- }
182
- if ('ondeviceorientationabsolute' in window) {
183
- window.addEventListener('deviceorientationabsolute', this.handleOrientation);
184
- }
240
+ this._addSensors();
185
241
  }
186
242
  return true;
187
243
  }