@capgo/capacitor-pedometer 7.0.0
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.
- package/CapgoCapacitorPedometer.podspec +17 -0
- package/LICENSE +21 -0
- package/Package.swift +28 -0
- package/README.md +297 -0
- package/android/build.gradle +57 -0
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/java/app/capgo/pedometer/CapacitorPedometerPlugin.java +246 -0
- package/dist/docs.json +455 -0
- package/dist/esm/definitions.d.ts +212 -0
- package/dist/esm/definitions.js +2 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/web.d.ts +10 -0
- package/dist/esm/web.js +28 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +42 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +45 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Sources/CapacitorPedometerPlugin/CapacitorPedometerPlugin.swift +189 -0
- package/ios/Tests/CapacitorPedometerPluginTests/CapacitorPedometerPluginTests.swift +9 -0
- package/package.json +90 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = 'CapgoCapacitorPedometer'
|
|
7
|
+
s.version = package['version']
|
|
8
|
+
s.summary = package['description']
|
|
9
|
+
s.license = package['license']
|
|
10
|
+
s.homepage = package['repository']['url']
|
|
11
|
+
s.author = package['author']
|
|
12
|
+
s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
|
|
13
|
+
s.source_files = 'ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}'
|
|
14
|
+
s.ios.deployment_target = '14.0'
|
|
15
|
+
s.dependency 'Capacitor'
|
|
16
|
+
s.swift_version = '5.1'
|
|
17
|
+
end
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Capgo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/Package.swift
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// swift-tools-version: 5.9
|
|
2
|
+
import PackageDescription
|
|
3
|
+
|
|
4
|
+
let package = Package(
|
|
5
|
+
name: "CapgoCapacitorPedometer",
|
|
6
|
+
platforms: [.iOS(.v14)],
|
|
7
|
+
products: [
|
|
8
|
+
.library(
|
|
9
|
+
name: "CapgoCapacitorPedometer",
|
|
10
|
+
targets: ["CapacitorPedometerPlugin"])
|
|
11
|
+
],
|
|
12
|
+
dependencies: [
|
|
13
|
+
.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "7.0.0")
|
|
14
|
+
],
|
|
15
|
+
targets: [
|
|
16
|
+
.target(
|
|
17
|
+
name: "CapacitorPedometerPlugin",
|
|
18
|
+
dependencies: [
|
|
19
|
+
.product(name: "Capacitor", package: "capacitor-swift-pm"),
|
|
20
|
+
.product(name: "Cordova", package: "capacitor-swift-pm")
|
|
21
|
+
],
|
|
22
|
+
path: "ios/Sources/CapacitorPedometerPlugin"),
|
|
23
|
+
.testTarget(
|
|
24
|
+
name: "CapacitorPedometerPluginTests",
|
|
25
|
+
dependencies: ["CapacitorPedometerPlugin"],
|
|
26
|
+
path: "ios/Tests/CapacitorPedometerPluginTests")
|
|
27
|
+
]
|
|
28
|
+
)
|
package/README.md
ADDED
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
# @capgo/capacitor-pedometer
|
|
2
|
+
|
|
3
|
+
Capacitor plugin for accessing pedometer data including steps, distance, pace, cadence, and floors.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @capgo/capacitor-pedometer
|
|
9
|
+
npx cap sync
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Configuration
|
|
13
|
+
|
|
14
|
+
### iOS
|
|
15
|
+
|
|
16
|
+
Add the following to your `Info.plist`:
|
|
17
|
+
|
|
18
|
+
```xml
|
|
19
|
+
<key>NSMotionUsageDescription</key>
|
|
20
|
+
<string>We need access to your motion data to track steps and activity</string>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Android
|
|
24
|
+
|
|
25
|
+
The plugin will automatically add the `ACTIVITY_RECOGNITION` permission to your `AndroidManifest.xml`.
|
|
26
|
+
|
|
27
|
+
For Android 10 (API 29) and above, you need to request the `ACTIVITY_RECOGNITION` permission at runtime.
|
|
28
|
+
|
|
29
|
+
## API
|
|
30
|
+
|
|
31
|
+
<docgen-index>
|
|
32
|
+
|
|
33
|
+
* [`getMeasurement(...)`](#getmeasurement)
|
|
34
|
+
* [`isAvailable()`](#isavailable)
|
|
35
|
+
* [`startMeasurementUpdates()`](#startmeasurementupdates)
|
|
36
|
+
* [`stopMeasurementUpdates()`](#stopmeasurementupdates)
|
|
37
|
+
* [`checkPermissions()`](#checkpermissions)
|
|
38
|
+
* [`requestPermissions()`](#requestpermissions)
|
|
39
|
+
* [`addListener('measurement', ...)`](#addlistenermeasurement-)
|
|
40
|
+
* [`removeAllListeners()`](#removealllisteners)
|
|
41
|
+
* [Interfaces](#interfaces)
|
|
42
|
+
* [Type Aliases](#type-aliases)
|
|
43
|
+
|
|
44
|
+
</docgen-index>
|
|
45
|
+
|
|
46
|
+
<docgen-api>
|
|
47
|
+
<!--Update the source file JSDoc comments and rerun docgen to update the docs below-->
|
|
48
|
+
|
|
49
|
+
### getMeasurement(...)
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
getMeasurement(options?: GetMeasurementOptions | undefined) => Promise<Measurement>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Get pedometer measurements for a specified time range.
|
|
56
|
+
|
|
57
|
+
| Param | Type |
|
|
58
|
+
| ------------- | ----------------------------------------------------------------------- |
|
|
59
|
+
| **`options`** | <code><a href="#getmeasurementoptions">GetMeasurementOptions</a></code> |
|
|
60
|
+
|
|
61
|
+
**Returns:** <code>Promise<<a href="#measurement">Measurement</a>></code>
|
|
62
|
+
|
|
63
|
+
**Since:** 0.0.1
|
|
64
|
+
|
|
65
|
+
--------------------
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
### isAvailable()
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
isAvailable() => Promise<IsAvailableResult>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Check which pedometer features are available on this device.
|
|
75
|
+
|
|
76
|
+
**Returns:** <code>Promise<<a href="#isavailableresult">IsAvailableResult</a>></code>
|
|
77
|
+
|
|
78
|
+
**Since:** 0.0.1
|
|
79
|
+
|
|
80
|
+
--------------------
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
### startMeasurementUpdates()
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
startMeasurementUpdates() => Promise<void>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Start receiving real-time pedometer measurement updates.
|
|
90
|
+
|
|
91
|
+
On **Android** and **iOS**, the `measurement` event is only fired after calling `startMeasurementUpdates()`.
|
|
92
|
+
|
|
93
|
+
**Since:** 0.0.1
|
|
94
|
+
|
|
95
|
+
--------------------
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
### stopMeasurementUpdates()
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
stopMeasurementUpdates() => Promise<void>
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Stop receiving real-time pedometer measurement updates.
|
|
105
|
+
|
|
106
|
+
**Since:** 0.0.1
|
|
107
|
+
|
|
108
|
+
--------------------
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
### checkPermissions()
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
checkPermissions() => Promise<PermissionStatus>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Check permission to access pedometer data.
|
|
118
|
+
|
|
119
|
+
On **Android**, this checks the `ACTIVITY_RECOGNITION` permission.
|
|
120
|
+
On **iOS**, this checks the motion usage permission.
|
|
121
|
+
|
|
122
|
+
**Returns:** <code>Promise<<a href="#permissionstatus">PermissionStatus</a>></code>
|
|
123
|
+
|
|
124
|
+
**Since:** 0.0.1
|
|
125
|
+
|
|
126
|
+
--------------------
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
### requestPermissions()
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
requestPermissions() => Promise<PermissionStatus>
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Request permission to access pedometer data.
|
|
136
|
+
|
|
137
|
+
On **Android**, this requests the `ACTIVITY_RECOGNITION` permission.
|
|
138
|
+
On **iOS**, this requests motion usage permission.
|
|
139
|
+
|
|
140
|
+
**Returns:** <code>Promise<<a href="#permissionstatus">PermissionStatus</a>></code>
|
|
141
|
+
|
|
142
|
+
**Since:** 0.0.1
|
|
143
|
+
|
|
144
|
+
--------------------
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
### addListener('measurement', ...)
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
addListener(eventName: 'measurement', listenerFunc: (event: MeasurementEvent) => void) => Promise<PluginListenerHandle>
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Called when a new pedometer measurement is received.
|
|
154
|
+
|
|
155
|
+
| Param | Type |
|
|
156
|
+
| ------------------ | ----------------------------------------------------------------------- |
|
|
157
|
+
| **`eventName`** | <code>'measurement'</code> |
|
|
158
|
+
| **`listenerFunc`** | <code>(event: <a href="#measurement">Measurement</a>) => void</code> |
|
|
159
|
+
|
|
160
|
+
**Returns:** <code>Promise<<a href="#pluginlistenerhandle">PluginListenerHandle</a>></code>
|
|
161
|
+
|
|
162
|
+
**Since:** 0.0.1
|
|
163
|
+
|
|
164
|
+
--------------------
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
### removeAllListeners()
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
removeAllListeners() => Promise<void>
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Remove all listeners for this plugin.
|
|
174
|
+
|
|
175
|
+
**Since:** 0.0.1
|
|
176
|
+
|
|
177
|
+
--------------------
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
### Interfaces
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
#### Measurement
|
|
184
|
+
|
|
185
|
+
| Prop | Type | Description | Since |
|
|
186
|
+
| ----------------------- | ------------------- | ----------------------------------------------------------------------------------- | ----- |
|
|
187
|
+
| **`numberOfSteps`** | <code>number</code> | The number of steps taken by the user. | 0.0.1 |
|
|
188
|
+
| **`distance`** | <code>number</code> | The estimated distance (in meters) traveled by the user. Only available on **iOS**. | 0.0.1 |
|
|
189
|
+
| **`floorsAscended`** | <code>number</code> | The approximate number of floors ascended. Only available on **iOS**. | 0.0.1 |
|
|
190
|
+
| **`floorsDescended`** | <code>number</code> | The approximate number of floors descended. Only available on **iOS**. | 0.0.1 |
|
|
191
|
+
| **`currentPace`** | <code>number</code> | The current pace (in seconds per meter). Only available on **iOS**. | 0.0.1 |
|
|
192
|
+
| **`currentCadence`** | <code>number</code> | The current cadence (steps per second). Only available on **iOS**. | 0.0.1 |
|
|
193
|
+
| **`averageActivePace`** | <code>number</code> | The average active pace (in seconds per meter). Only available on **iOS**. | 0.0.1 |
|
|
194
|
+
| **`startDate`** | <code>number</code> | The start time of this measurement (milliseconds since epoch). | 0.0.1 |
|
|
195
|
+
| **`endDate`** | <code>number</code> | The end time of this measurement (milliseconds since epoch). | 0.0.1 |
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
#### GetMeasurementOptions
|
|
199
|
+
|
|
200
|
+
| Prop | Type | Description | Since |
|
|
201
|
+
| ----------- | ------------------- | ----------------------------------------------------------------------------------------- | ----- |
|
|
202
|
+
| **`start`** | <code>number</code> | The start time for the measurement query (milliseconds since epoch). Required on **iOS**. | 0.0.1 |
|
|
203
|
+
| **`end`** | <code>number</code> | The end time for the measurement query (milliseconds since epoch). Required on **iOS**. | 0.0.1 |
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
#### IsAvailableResult
|
|
207
|
+
|
|
208
|
+
| Prop | Type | Description | Since |
|
|
209
|
+
| ------------------- | -------------------- | --------------------------------------------------------------------------------------------------------- | ----- |
|
|
210
|
+
| **`stepCounting`** | <code>boolean</code> | Whether step counting is available. | 0.0.1 |
|
|
211
|
+
| **`distance`** | <code>boolean</code> | Whether distance measurement is available. Only `true` on **iOS** devices that support distance tracking. | 0.0.1 |
|
|
212
|
+
| **`pace`** | <code>boolean</code> | Whether pace measurement is available. Only `true` on **iOS** devices that support pace tracking. | 0.0.1 |
|
|
213
|
+
| **`cadence`** | <code>boolean</code> | Whether cadence measurement is available. Only `true` on **iOS** devices that support cadence tracking. | 0.0.1 |
|
|
214
|
+
| **`floorCounting`** | <code>boolean</code> | Whether floor counting is available. Only `true` on **iOS** devices that support floor tracking. | 0.0.1 |
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
#### PermissionStatus
|
|
218
|
+
|
|
219
|
+
| Prop | Type | Description | Since |
|
|
220
|
+
| ------------------------- | ------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- |
|
|
221
|
+
| **`activityRecognition`** | <code>'prompt' \| 'prompt-with-rationale' \| 'granted' \| 'denied'</code> | Permission state for activity recognition. On **Android**, this is the `ACTIVITY_RECOGNITION` permission. On **iOS**, this is the motion usage permission. | 0.0.1 |
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
#### PluginListenerHandle
|
|
225
|
+
|
|
226
|
+
| Prop | Type |
|
|
227
|
+
| ------------ | ----------------------------------------- |
|
|
228
|
+
| **`remove`** | <code>() => Promise<void></code> |
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
### Type Aliases
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
#### MeasurementEvent
|
|
235
|
+
|
|
236
|
+
<code><a href="#measurement">Measurement</a></code>
|
|
237
|
+
|
|
238
|
+
</docgen-api>
|
|
239
|
+
|
|
240
|
+
## Usage
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
import { CapacitorPedometer } from '@capgo/capacitor-pedometer';
|
|
244
|
+
|
|
245
|
+
// Check availability
|
|
246
|
+
const availability = await CapacitorPedometer.isAvailable();
|
|
247
|
+
console.log('Features available:', availability);
|
|
248
|
+
|
|
249
|
+
// Check and request permissions
|
|
250
|
+
const permission = await CapacitorPedometer.checkPermissions();
|
|
251
|
+
if (permission.activityRecognition !== 'granted') {
|
|
252
|
+
await CapacitorPedometer.requestPermissions();
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Start real-time updates
|
|
256
|
+
await CapacitorPedometer.addListener('measurement', (data) => {
|
|
257
|
+
console.log('Steps:', data.numberOfSteps);
|
|
258
|
+
console.log('Distance:', data.distance);
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
await CapacitorPedometer.startMeasurementUpdates();
|
|
262
|
+
|
|
263
|
+
// Query historical data (iOS only - requires start and end timestamps)
|
|
264
|
+
const now = Date.now();
|
|
265
|
+
const yesterday = now - (24 * 60 * 60 * 1000);
|
|
266
|
+
const measurement = await CapacitorPedometer.getMeasurement({
|
|
267
|
+
start: yesterday,
|
|
268
|
+
end: now
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
// Stop updates
|
|
272
|
+
await CapacitorPedometer.stopMeasurementUpdates();
|
|
273
|
+
await CapacitorPedometer.removeAllListeners();
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## Platform Support
|
|
277
|
+
|
|
278
|
+
| Feature | Android | iOS |
|
|
279
|
+
|---------|---------|-----|
|
|
280
|
+
| Step Counting | ✅ | ✅ |
|
|
281
|
+
| Distance | ❌ | ✅ |
|
|
282
|
+
| Pace | ❌ | ✅ |
|
|
283
|
+
| Cadence | ❌ | ✅ |
|
|
284
|
+
| Floor Counting | ❌ | ✅ |
|
|
285
|
+
| Historical Queries | ❌ | ✅ |
|
|
286
|
+
|
|
287
|
+
## Notes
|
|
288
|
+
|
|
289
|
+
- On **Android**, only step counting is available. The plugin uses the `TYPE_STEP_COUNTER` sensor.
|
|
290
|
+
- On **iOS**, all features are available on supported devices using `CMPedometer`.
|
|
291
|
+
- Historical data queries require explicit `start` and `end` timestamps on iOS.
|
|
292
|
+
- Android's step counter gives cumulative steps since last device reboot; the plugin tracks the delta.
|
|
293
|
+
- Measurements are paused when the app is in the background.
|
|
294
|
+
|
|
295
|
+
## License
|
|
296
|
+
|
|
297
|
+
MIT
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
ext {
|
|
2
|
+
junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
|
|
3
|
+
androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.7.0'
|
|
4
|
+
androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.2.1'
|
|
5
|
+
androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.6.1'
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
buildscript {
|
|
9
|
+
repositories {
|
|
10
|
+
google()
|
|
11
|
+
mavenCentral()
|
|
12
|
+
}
|
|
13
|
+
dependencies {
|
|
14
|
+
classpath 'com.android.tools.build:gradle:8.7.2'
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
apply plugin: 'com.android.library'
|
|
19
|
+
|
|
20
|
+
android {
|
|
21
|
+
namespace "app.capgo.pedometer"
|
|
22
|
+
compileSdk project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 35
|
|
23
|
+
defaultConfig {
|
|
24
|
+
minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 23
|
|
25
|
+
targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 35
|
|
26
|
+
versionCode 1
|
|
27
|
+
versionName "1.0"
|
|
28
|
+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
29
|
+
}
|
|
30
|
+
buildTypes {
|
|
31
|
+
release {
|
|
32
|
+
minifyEnabled false
|
|
33
|
+
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
lintOptions {
|
|
37
|
+
abortOnError false
|
|
38
|
+
}
|
|
39
|
+
compileOptions {
|
|
40
|
+
sourceCompatibility JavaVersion.VERSION_21
|
|
41
|
+
targetCompatibility JavaVersion.VERSION_21
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
repositories {
|
|
46
|
+
google()
|
|
47
|
+
mavenCentral()
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
dependencies {
|
|
51
|
+
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
|
52
|
+
implementation project(':capacitor-android')
|
|
53
|
+
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
|
|
54
|
+
testImplementation "junit:junit:$junitVersion"
|
|
55
|
+
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
|
|
56
|
+
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
|
|
57
|
+
}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
package app.capgo.pedometer;
|
|
2
|
+
|
|
3
|
+
import android.Manifest;
|
|
4
|
+
import android.content.Context;
|
|
5
|
+
import android.content.pm.PackageManager;
|
|
6
|
+
import android.hardware.Sensor;
|
|
7
|
+
import android.hardware.SensorEvent;
|
|
8
|
+
import android.hardware.SensorEventListener;
|
|
9
|
+
import android.hardware.SensorManager;
|
|
10
|
+
import android.os.Build;
|
|
11
|
+
import androidx.annotation.Nullable;
|
|
12
|
+
import com.getcapacitor.JSObject;
|
|
13
|
+
import com.getcapacitor.PermissionState;
|
|
14
|
+
import com.getcapacitor.Plugin;
|
|
15
|
+
import com.getcapacitor.PluginCall;
|
|
16
|
+
import com.getcapacitor.PluginMethod;
|
|
17
|
+
import com.getcapacitor.annotation.CapacitorPlugin;
|
|
18
|
+
import com.getcapacitor.annotation.Permission;
|
|
19
|
+
import com.getcapacitor.annotation.PermissionCallback;
|
|
20
|
+
|
|
21
|
+
@CapacitorPlugin(
|
|
22
|
+
name = "CapacitorPedometer",
|
|
23
|
+
permissions = { @Permission(strings = { Manifest.permission.ACTIVITY_RECOGNITION }, alias = "activityRecognition") }
|
|
24
|
+
)
|
|
25
|
+
public class CapacitorPedometerPlugin extends Plugin implements SensorEventListener {
|
|
26
|
+
|
|
27
|
+
private final String PLUGIN_VERSION = "7.0.0";
|
|
28
|
+
private static final String PERMISSION_GRANTED = "granted";
|
|
29
|
+
private static final String PERMISSION_DENIED = "denied";
|
|
30
|
+
private static final String PERMISSION_PROMPT = "prompt";
|
|
31
|
+
private static final String PERMISSION_PROMPT_WITH_RATIONALE = "prompt-with-rationale";
|
|
32
|
+
|
|
33
|
+
@Nullable
|
|
34
|
+
private SensorManager sensorManager;
|
|
35
|
+
|
|
36
|
+
@Nullable
|
|
37
|
+
private Sensor stepCounter;
|
|
38
|
+
|
|
39
|
+
private int initialStepCount = -1;
|
|
40
|
+
private int currentStepCount = 0;
|
|
41
|
+
private long measurementStartTime = 0;
|
|
42
|
+
|
|
43
|
+
private boolean updatesActive = false;
|
|
44
|
+
|
|
45
|
+
@Override
|
|
46
|
+
public void load() {
|
|
47
|
+
Context context = getContext();
|
|
48
|
+
sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
|
|
49
|
+
if (sensorManager != null) {
|
|
50
|
+
stepCounter = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@PluginMethod
|
|
55
|
+
public void getMeasurement(PluginCall call) {
|
|
56
|
+
if (stepCounter == null) {
|
|
57
|
+
call.reject("Step counter sensor not available on this device.");
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (!hasActivityRecognitionPermission()) {
|
|
62
|
+
call.reject("Activity recognition permission not granted.");
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
JSObject result = createMeasurementObject();
|
|
67
|
+
call.resolve(result);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
@PluginMethod
|
|
71
|
+
public void isAvailable(PluginCall call) {
|
|
72
|
+
JSObject result = new JSObject();
|
|
73
|
+
result.put("stepCounting", stepCounter != null);
|
|
74
|
+
// Android doesn't support these advanced features
|
|
75
|
+
result.put("distance", false);
|
|
76
|
+
result.put("pace", false);
|
|
77
|
+
result.put("cadence", false);
|
|
78
|
+
result.put("floorCounting", false);
|
|
79
|
+
call.resolve(result);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
@PluginMethod
|
|
83
|
+
public void startMeasurementUpdates(PluginCall call) {
|
|
84
|
+
if (stepCounter == null) {
|
|
85
|
+
call.reject("Step counter sensor not available on this device.");
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (!hasActivityRecognitionPermission()) {
|
|
90
|
+
call.reject("Activity recognition permission not granted.");
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (updatesActive) {
|
|
95
|
+
call.resolve();
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
measurementStartTime = System.currentTimeMillis();
|
|
100
|
+
initialStepCount = -1;
|
|
101
|
+
|
|
102
|
+
if (sensorManager != null && sensorManager.registerListener(this, stepCounter, SensorManager.SENSOR_DELAY_UI)) {
|
|
103
|
+
updatesActive = true;
|
|
104
|
+
call.resolve();
|
|
105
|
+
} else {
|
|
106
|
+
call.reject("Failed to register step counter listener.");
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
@PluginMethod
|
|
111
|
+
public void stopMeasurementUpdates(PluginCall call) {
|
|
112
|
+
if (sensorManager != null && updatesActive) {
|
|
113
|
+
sensorManager.unregisterListener(this);
|
|
114
|
+
updatesActive = false;
|
|
115
|
+
initialStepCount = -1;
|
|
116
|
+
currentStepCount = 0;
|
|
117
|
+
}
|
|
118
|
+
call.resolve();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
@PluginMethod
|
|
122
|
+
public void checkPermissions(PluginCall call) {
|
|
123
|
+
JSObject result = new JSObject();
|
|
124
|
+
result.put("activityRecognition", getPermissionState());
|
|
125
|
+
call.resolve(result);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
@PluginMethod
|
|
129
|
+
public void requestPermissions(PluginCall call) {
|
|
130
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
|
131
|
+
if (getPermissionState(Manifest.permission.ACTIVITY_RECOGNITION) != PermissionState.GRANTED) {
|
|
132
|
+
requestPermissionForAlias("activityRecognition", call, "permissionCallback");
|
|
133
|
+
} else {
|
|
134
|
+
JSObject result = new JSObject();
|
|
135
|
+
result.put("activityRecognition", PERMISSION_GRANTED);
|
|
136
|
+
call.resolve(result);
|
|
137
|
+
}
|
|
138
|
+
} else {
|
|
139
|
+
// No permission needed on older Android versions
|
|
140
|
+
JSObject result = new JSObject();
|
|
141
|
+
result.put("activityRecognition", PERMISSION_GRANTED);
|
|
142
|
+
call.resolve(result);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
@PermissionCallback
|
|
147
|
+
private void permissionCallback(PluginCall call) {
|
|
148
|
+
JSObject result = new JSObject();
|
|
149
|
+
result.put("activityRecognition", getPermissionState());
|
|
150
|
+
call.resolve(result);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
@PluginMethod
|
|
154
|
+
public void removeAllListeners(PluginCall call) {
|
|
155
|
+
super.removeAllListeners(call);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
@Override
|
|
159
|
+
public void handleOnPause() {
|
|
160
|
+
if (sensorManager != null && updatesActive) {
|
|
161
|
+
sensorManager.unregisterListener(this);
|
|
162
|
+
}
|
|
163
|
+
super.handleOnPause();
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
@Override
|
|
167
|
+
public void handleOnResume() {
|
|
168
|
+
super.handleOnResume();
|
|
169
|
+
if (updatesActive && sensorManager != null && stepCounter != null && hasActivityRecognitionPermission()) {
|
|
170
|
+
sensorManager.registerListener(this, stepCounter, SensorManager.SENSOR_DELAY_UI);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
@Override
|
|
175
|
+
public void handleOnDestroy() {
|
|
176
|
+
if (sensorManager != null) {
|
|
177
|
+
sensorManager.unregisterListener(this);
|
|
178
|
+
}
|
|
179
|
+
super.handleOnDestroy();
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
@Override
|
|
183
|
+
public void onSensorChanged(SensorEvent event) {
|
|
184
|
+
if (event.sensor.getType() != Sensor.TYPE_STEP_COUNTER) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
int totalSteps = (int) event.values[0];
|
|
189
|
+
|
|
190
|
+
if (initialStepCount == -1) {
|
|
191
|
+
initialStepCount = totalSteps;
|
|
192
|
+
currentStepCount = 0;
|
|
193
|
+
} else {
|
|
194
|
+
currentStepCount = totalSteps - initialStepCount;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
JSObject payload = createMeasurementObject();
|
|
198
|
+
notifyListeners("measurement", payload);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
@Override
|
|
202
|
+
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
|
203
|
+
// No-op
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
private JSObject createMeasurementObject() {
|
|
207
|
+
JSObject measurement = new JSObject();
|
|
208
|
+
measurement.put("numberOfSteps", currentStepCount);
|
|
209
|
+
measurement.put("startDate", measurementStartTime);
|
|
210
|
+
measurement.put("endDate", System.currentTimeMillis());
|
|
211
|
+
return measurement;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
private boolean hasActivityRecognitionPermission() {
|
|
215
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
|
216
|
+
return getPermissionState(Manifest.permission.ACTIVITY_RECOGNITION) == PermissionState.GRANTED;
|
|
217
|
+
}
|
|
218
|
+
return true; // No permission needed on older Android versions
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
private String getPermissionState() {
|
|
222
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
|
223
|
+
PermissionState state = getPermissionState(Manifest.permission.ACTIVITY_RECOGNITION);
|
|
224
|
+
switch (state) {
|
|
225
|
+
case GRANTED:
|
|
226
|
+
return PERMISSION_GRANTED;
|
|
227
|
+
case DENIED:
|
|
228
|
+
return PERMISSION_DENIED;
|
|
229
|
+
default:
|
|
230
|
+
return PERMISSION_PROMPT;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return PERMISSION_GRANTED; // No permission needed on older Android versions
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
@PluginMethod
|
|
237
|
+
public void getPluginVersion(final PluginCall call) {
|
|
238
|
+
try {
|
|
239
|
+
final JSObject ret = new JSObject();
|
|
240
|
+
ret.put("version", this.PLUGIN_VERSION);
|
|
241
|
+
call.resolve(ret);
|
|
242
|
+
} catch (final Exception e) {
|
|
243
|
+
call.reject("Could not get plugin version", e);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|