@cariva-dev/exercise-sdk 2.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.
Files changed (82) hide show
  1. package/CarivaExerciseSdk.podspec +20 -0
  2. package/README.md +374 -0
  3. package/android/build.gradle +66 -0
  4. package/android/src/main/AndroidManifest.xml +40 -0
  5. package/android/src/main/java/com/carivaexercisesdk/CarivaExerciseSdkPackage.kt +30 -0
  6. package/android/src/main/java/com/carivaexercisesdk/HealthConnectModule.kt +222 -0
  7. package/android/src/main/java/com/carivaexercisesdk/HealthConnectPermissionUsageActivity.kt +11 -0
  8. package/android/src/main/java/com/carivaexercisesdk/HealthConnectPermissionsRationaleActivity.kt +11 -0
  9. package/android/src/main/java/com/carivaexercisesdk/Pagination.kt +23 -0
  10. package/android/src/main/java/com/carivaexercisesdk/application/connection/command/ConnectCommand.kt +12 -0
  11. package/android/src/main/java/com/carivaexercisesdk/application/connection/dto/ConnectResultDto.kt +13 -0
  12. package/android/src/main/java/com/carivaexercisesdk/application/connection/handler/ConnectHandler.kt +79 -0
  13. package/android/src/main/java/com/carivaexercisesdk/application/connection/port/HealthConnectConnectionPort.kt +16 -0
  14. package/android/src/main/java/com/carivaexercisesdk/application/connection/port/PermissionRequestPort.kt +5 -0
  15. package/android/src/main/java/com/carivaexercisesdk/application/datasource/command/SetDatasourcePolicyCommand.kt +6 -0
  16. package/android/src/main/java/com/carivaexercisesdk/application/datasource/handler/GetDatasourcePolicyHandler.kt +10 -0
  17. package/android/src/main/java/com/carivaexercisesdk/application/datasource/handler/SetDatasourcePolicyHandler.kt +22 -0
  18. package/android/src/main/java/com/carivaexercisesdk/application/datasource/port/DatasourcePolicyRepository.kt +9 -0
  19. package/android/src/main/java/com/carivaexercisesdk/application/exercise/dto/BasalReadResultDto.kt +11 -0
  20. package/android/src/main/java/com/carivaexercisesdk/application/exercise/dto/ExerciseDataDto.kt +41 -0
  21. package/android/src/main/java/com/carivaexercisesdk/application/exercise/handler/GetExerciseDataHandler.kt +346 -0
  22. package/android/src/main/java/com/carivaexercisesdk/application/exercise/port/ExerciseRecordPort.kt +45 -0
  23. package/android/src/main/java/com/carivaexercisesdk/application/exercise/query/GetExerciseDataQuery.kt +9 -0
  24. package/android/src/main/java/com/carivaexercisesdk/domain/connection/entity/ConnectionAggregate.kt +13 -0
  25. package/android/src/main/java/com/carivaexercisesdk/domain/connection/service/ConnectionDecisionService.kt +37 -0
  26. package/android/src/main/java/com/carivaexercisesdk/domain/connection/valueobject/ConnectionNextAction.kt +8 -0
  27. package/android/src/main/java/com/carivaexercisesdk/domain/connection/valueobject/HealthConnectStatus.kt +8 -0
  28. package/android/src/main/java/com/carivaexercisesdk/domain/connection/valueobject/PermissionScope.kt +36 -0
  29. package/android/src/main/java/com/carivaexercisesdk/domain/datasource/entity/DatasourcePolicy.kt +8 -0
  30. package/android/src/main/java/com/carivaexercisesdk/domain/datasource/valueobject/DatasourceType.kt +14 -0
  31. package/android/src/main/java/com/carivaexercisesdk/domain/exercise/services/ExerciseDomainService.kt +89 -0
  32. package/android/src/main/java/com/carivaexercisesdk/domain/exercise/services/HealthConnectCaloriesFallbackMerger.kt +351 -0
  33. package/android/src/main/java/com/carivaexercisesdk/domain/exercise/services/HealthConnectInternalsConstants.kt +55 -0
  34. package/android/src/main/java/com/carivaexercisesdk/domain/exercise/services/HealthConnectModuleInternals.kt +316 -0
  35. package/android/src/main/java/com/carivaexercisesdk/domain/exercise/services/HealthConnectOverlapNormalizer.kt +400 -0
  36. package/android/src/main/java/com/carivaexercisesdk/domain/exercise/services/HealthConnectSourceTrust.kt +249 -0
  37. package/android/src/main/java/com/carivaexercisesdk/domain/exercise/services/HealthConnectUnifiedRecordBuilder.kt +316 -0
  38. package/android/src/main/java/com/carivaexercisesdk/infrastructure/healthconnect/HealthConnectConnectionAdapter.kt +156 -0
  39. package/android/src/main/java/com/carivaexercisesdk/infrastructure/healthconnect/HealthConnectExerciseRecordAdapter.kt +464 -0
  40. package/android/src/main/java/com/carivaexercisesdk/infrastructure/persistence/InMemoryDatasourcePolicyRepository.kt +21 -0
  41. package/android/src/main/java/com/carivaexercisesdk/infrastructure/reactnative/ConnectResultMapper.kt +23 -0
  42. package/android/src/main/java/com/carivaexercisesdk/infrastructure/reactnative/DatasourcePolicyJsonParser.kt +51 -0
  43. package/android/src/main/java/com/carivaexercisesdk/infrastructure/reactnative/DatasourcePolicyMapper.kt +46 -0
  44. package/android/src/main/java/com/carivaexercisesdk/infrastructure/reactnative/ExerciseDataMapper.kt +99 -0
  45. package/android/src/test/java/com/carivaexercisesdk/ArchitectureDependencyRuleTest.kt +60 -0
  46. package/android/src/test/java/com/carivaexercisesdk/HealthConnectModuleDatasourceParserTest.kt +69 -0
  47. package/android/src/test/java/com/carivaexercisesdk/HealthConnectModuleInternalsTest.kt +406 -0
  48. package/android/src/test/java/com/carivaexercisesdk/application/connection/handler/ConnectHandlerTest.kt +153 -0
  49. package/android/src/test/java/com/carivaexercisesdk/application/datasource/handler/DatasourcePolicyRoundTripTest.kt +63 -0
  50. package/android/src/test/java/com/carivaexercisesdk/application/datasource/handler/SetDatasourcePolicyHandlerTest.kt +42 -0
  51. package/android/src/test/java/com/carivaexercisesdk/domain/connection/service/ConnectionDecisionServiceTest.kt +68 -0
  52. package/android/src/test/java/com/carivaexercisesdk/infrastructure/reactnative/DatasourcePolicyMapperTest.kt +22 -0
  53. package/ios/CarivaExerciseSdk.h +5 -0
  54. package/ios/CarivaExerciseSdk.mm +7 -0
  55. package/lib/module/connect/index.js +7 -0
  56. package/lib/module/connect/index.js.map +1 -0
  57. package/lib/module/datasource/index.js +10 -0
  58. package/lib/module/datasource/index.js.map +1 -0
  59. package/lib/module/exercise/index.js +7 -0
  60. package/lib/module/exercise/index.js.map +1 -0
  61. package/lib/module/index.js +6 -0
  62. package/lib/module/index.js.map +1 -0
  63. package/lib/module/native/module.js +13 -0
  64. package/lib/module/native/module.js.map +1 -0
  65. package/lib/module/package.json +1 -0
  66. package/lib/typescript/package.json +1 -0
  67. package/lib/typescript/src/connect/index.d.ts +16 -0
  68. package/lib/typescript/src/connect/index.d.ts.map +1 -0
  69. package/lib/typescript/src/datasource/index.d.ts +12 -0
  70. package/lib/typescript/src/datasource/index.d.ts.map +1 -0
  71. package/lib/typescript/src/exercise/index.d.ts +64 -0
  72. package/lib/typescript/src/exercise/index.d.ts.map +1 -0
  73. package/lib/typescript/src/index.d.ts +4 -0
  74. package/lib/typescript/src/index.d.ts.map +1 -0
  75. package/lib/typescript/src/native/module.d.ts +14 -0
  76. package/lib/typescript/src/native/module.d.ts.map +1 -0
  77. package/package.json +127 -0
  78. package/src/connect/index.ts +34 -0
  79. package/src/datasource/index.ts +20 -0
  80. package/src/exercise/index.ts +75 -0
  81. package/src/index.tsx +22 -0
  82. package/src/native/module.ts +23 -0
@@ -0,0 +1,20 @@
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 = "CarivaExerciseSdk"
7
+ s.version = package["version"]
8
+ s.summary = package["description"]
9
+ s.homepage = package["homepage"]
10
+ s.license = package["license"]
11
+ s.authors = package["author"]
12
+
13
+ s.platforms = { :ios => min_ios_version_supported }
14
+ s.source = { :git => "https://github.com/cariva/cariva-exercise-sdk.git", :tag => "#{s.version}" }
15
+
16
+ s.source_files = "ios/**/*.{h,m,mm,swift,cpp}"
17
+ s.private_header_files = "ios/**/*.h"
18
+
19
+ install_modules_dependencies(s)
20
+ end
package/README.md ADDED
@@ -0,0 +1,374 @@
1
+ # @cariva/exercise-sdk
2
+
3
+ React Native SDK for reading exercise and activity data from **Android Health Connect**.
4
+
5
+ ## Platform Support
6
+
7
+ | Platform | Status |
8
+ |----------|--------|
9
+ | Android | Supported (Health Connect) |
10
+ | iOS | Out of scope for this release |
11
+
12
+ ---
13
+
14
+ ## Requirements
15
+
16
+ - React Native **0.68+** (New Architecture / Turbo Module compatible)
17
+ - Android **API level 26+**
18
+ - [Health Connect](https://play.google.com/store/apps/details?id=com.google.android.apps.healthdata) installed on the device (or available through Play Services on Android 14+)
19
+
20
+ ---
21
+
22
+ ## Installation
23
+
24
+ ### 1. Install the package
25
+
26
+ ```sh
27
+ # npm
28
+ npm install @cariva/exercise-sdk
29
+
30
+ # yarn
31
+ yarn add @cariva/exercise-sdk
32
+ ```
33
+
34
+ ### 2. Android — AndroidManifest.xml
35
+
36
+ The SDK ships its own manifest with Health Connect permissions, but you must also declare **two additional entries** in your app's `AndroidManifest.xml`:
37
+
38
+ #### 2a. Add the `<queries>` block (package visibility)
39
+
40
+ Inside the root `<manifest>` element:
41
+
42
+ ```xml
43
+ <queries>
44
+ <package android:name="com.google.android.apps.healthdata" />
45
+ <package android:name="com.google.android.healthconnect.controller" />
46
+ </queries>
47
+ ```
48
+
49
+ #### 2b. Add the Health Connect permission rationale activities
50
+
51
+ Inside the `<application>` element:
52
+
53
+ ```xml
54
+ <!-- Required by Health Connect: shown when user taps "Privacy policy" in permissions dialog -->
55
+ <activity
56
+ android:name="com.carivaexercisesdk.HealthConnectPermissionsRationaleActivity"
57
+ android:exported="true">
58
+ <intent-filter>
59
+ <action android:name="androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE" />
60
+ </intent-filter>
61
+ </activity>
62
+
63
+ <!-- Required by Health Connect: shown from Android Settings > App permissions -->
64
+ <activity
65
+ android:name="com.carivaexercisesdk.HealthConnectPermissionUsageActivity"
66
+ android:exported="true"
67
+ android:permission="android.permission.START_VIEW_PERMISSION_USAGE">
68
+ <intent-filter>
69
+ <action android:name="android.intent.action.VIEW_PERMISSION_USAGE" />
70
+ <category android:name="android.intent.category.HEALTH_PERMISSIONS" />
71
+ </intent-filter>
72
+ </activity>
73
+ ```
74
+
75
+ > **Note:** These activities are part of the Health Connect compliance requirement. The app will still build without them, but Health Connect permission management will not work correctly.
76
+
77
+ ### 3. iOS
78
+
79
+ No additional setup is required. The SDK is a no-op on iOS.
80
+
81
+ ---
82
+
83
+ ## Quick Start
84
+
85
+ ```ts
86
+ import {
87
+ connect,
88
+ getExerciseData,
89
+ setAllowDatasource,
90
+ getAllowDatasource,
91
+ } from '@cariva/exercise-sdk';
92
+
93
+ // 1. Connect and request permissions
94
+ const status = await connect({
95
+ onMissingApp: 'status',
96
+ requestPermission: true,
97
+ permissionScope: ['steps', 'calories'],
98
+ });
99
+
100
+ if (!status.ready) {
101
+ console.log('Next action required:', status.nextAction);
102
+ // e.g. 'INSTALL_HEALTH_CONNECT' | 'REQUEST_PERMISSION' | ...
103
+ return;
104
+ }
105
+
106
+ // 2. Fetch exercise data
107
+ const data = await getExerciseData({
108
+ sinceMillis: Date.now() - 7 * 24 * 60 * 60 * 1000, // last 7 days
109
+ untilMillis: Date.now(),
110
+ type: 'all',
111
+ bucketPeriod: 'daily',
112
+ });
113
+
114
+ console.log('Records:', data.records);
115
+ console.log('Total steps:', data.totalSteps);
116
+ ```
117
+
118
+ ---
119
+
120
+ ## API Reference
121
+
122
+ ### Migration Notes (v2.0.0)
123
+
124
+ - `connect()` no longer checks Google Fit installation.
125
+ - `ConnectResult.googleFitInstalled` was removed.
126
+ - `ConnectResult.nextAction` no longer returns `INSTALL_GOOGLE_FIT`.
127
+ - Readiness now depends only on Health Connect:
128
+ `ready = healthConnectInstalled && healthConnectStatus === 'AVAILABLE' && hasPermissions`.
129
+
130
+ ### `connect(options?)`
131
+
132
+ Checks Health Connect availability and optionally requests permissions.
133
+
134
+ ```ts
135
+ type ConnectOptions = {
136
+ onMissingApp?: 'status' | 'open'; // 'open' navigates to Health Connect in Play Store
137
+ requestPermission?: boolean; // default: false
138
+ permissionScope?: Array<'steps' | 'activetimes' | 'calories' | 'distances'>;
139
+ };
140
+
141
+ type ConnectResult = {
142
+ ready: boolean;
143
+ healthConnectInstalled: boolean;
144
+ healthConnectStatus: 'AVAILABLE' | 'PROVIDER_UPDATE_REQUIRED' | 'UNAVAILABLE' | 'UNKNOWN';
145
+ hasPermissions: boolean;
146
+ nextAction:
147
+ | 'INSTALL_HEALTH_CONNECT'
148
+ | 'UPDATE_HEALTH_CONNECT'
149
+ | 'REQUEST_PERMISSION'
150
+ | 'NONE';
151
+ requestedPermissions?: string[];
152
+ };
153
+ ```
154
+
155
+ | Option | Type | Default | Description |
156
+ |--------|------|---------|-------------|
157
+ | `onMissingApp` | `'status' \| 'open'` | `'status'` | `'open'` opens Play Store for Health Connect only |
158
+ | `requestPermission` | `boolean` | `false` | Trigger the Health Connect permission dialog |
159
+ | `permissionScope` | `PermissionScope[]` | all scopes | Limit which permissions are requested |
160
+
161
+ ---
162
+
163
+ ### `getExerciseData(options)`
164
+
165
+ Reads aggregated exercise data from Health Connect.
166
+
167
+ ```ts
168
+ type GetExerciseDataOptions = {
169
+ sinceMillis: number;
170
+ untilMillis: number;
171
+ type?: 'steps' | 'activetimes' | 'calories' | 'distances' | 'all'; // default: 'all'
172
+ bucketPeriod?: 'hourly' | 'daily'; // default: 'hourly'
173
+ debug?: boolean; // default: false
174
+ };
175
+
176
+ type ExerciseData = {
177
+ totalSteps: number;
178
+ totalKcal: number;
179
+ totalDistanceMeters: number;
180
+ totalActiveTimeMillis: number;
181
+ totalActiveTime?: number; // deprecated alias for backward compatibility
182
+ timeZone: string;
183
+ records: UnifiedIntervalRecord[];
184
+ warnings?: string[];
185
+ integrity?: {
186
+ projectionPreserved: boolean;
187
+ roundingScale: number;
188
+ };
189
+ diagnostics?: {
190
+ fallbackUsedSegments: number;
191
+ fallbackSuppressedSegments: number;
192
+ idleGateSuppressedSegments: number;
193
+ basalSeedApplied: boolean;
194
+ seededFromBeforeSince: boolean;
195
+ basalSeedAgeHours?: number;
196
+ };
197
+ debug?: {
198
+ directActiveCaloriesKcal: number;
199
+ totalCaloriesKcal: number;
200
+ basalCaloriesKcal: number;
201
+ mergedActiveCaloriesKcal: number;
202
+ fallbackContributionKcal: number;
203
+ fallbackUsedSegments: number;
204
+ fallbackSuppressedSegments: number;
205
+ idleGateSuppressedSegments: number;
206
+ basalSeedApplied: boolean;
207
+ seededFromBeforeSince: boolean;
208
+ basalSeedAgeHours?: number;
209
+ basalIntervalsCount: number;
210
+ };
211
+ };
212
+ ```
213
+
214
+ > Periods longer than **90 days** reject with error code `E_INVALID_PERIOD`.
215
+ > Invalid `permissionScope` values reject with error code `E_INVALID_PERMISSION_SCOPE`.
216
+
217
+ ---
218
+
219
+ ### `setAllowDatasource(config)`
220
+
221
+ Configures which data sources to exclude from results.
222
+
223
+ ```ts
224
+ type DatasourceType = 'manual_input' | 'device' | 'app' | 'unknown';
225
+
226
+ type DatasourceConfig = {
227
+ blacklist: DatasourceType[];
228
+ };
229
+
230
+ // Example: exclude manually-entered data
231
+ await setAllowDatasource({ blacklist: ['manual_input'] });
232
+ ```
233
+
234
+ ---
235
+
236
+ ### `getAllowDatasource()`
237
+
238
+ Returns the current datasource blacklist configuration.
239
+
240
+ ```ts
241
+ const config = await getAllowDatasource();
242
+ // => { blacklist: ['manual_input'] }
243
+ ```
244
+
245
+ ---
246
+
247
+ ## Unified Record Schema
248
+
249
+ Every record in `data.records` follows this shape regardless of the `type` queried:
250
+
251
+ ```ts
252
+ type UnifiedIntervalRecord = {
253
+ steps: number;
254
+ activeCalories: number;
255
+ activeCaloriesUnit: 'kcal';
256
+ distance: number;
257
+ distanceUnit: 'km';
258
+ activeTime: number;
259
+ activeTimeUnit: 'milliseconds';
260
+ startDate: string; // ISO offset string, e.g. "2026-02-16T08:00:00+07:00"
261
+ endDate: string;
262
+ meta: {
263
+ source: string;
264
+ device: string;
265
+ deviceModel: string;
266
+ trustLevel: 'trusted' | 'low_confidence';
267
+ };
268
+ };
269
+ ```
270
+
271
+ Example record:
272
+
273
+ ```json
274
+ {
275
+ "steps": 1300,
276
+ "activeCalories": 60.2,
277
+ "activeCaloriesUnit": "kcal",
278
+ "distance": 1.0,
279
+ "distanceUnit": "km",
280
+ "activeTime": 1200000,
281
+ "activeTimeUnit": "milliseconds",
282
+ "startDate": "2026-02-16T08:30:00+07:00",
283
+ "endDate": "2026-02-16T09:00:00+07:00",
284
+ "meta": {
285
+ "source": "device",
286
+ "device": "com.google.android.apps.healthdata",
287
+ "deviceModel": "Pixel Watch 2",
288
+ "trustLevel": "trusted"
289
+ }
290
+ }
291
+ ```
292
+
293
+ ---
294
+
295
+ ## Overlap Handling
296
+
297
+ The SDK automatically de-duplicates overlapping Health Connect records:
298
+
299
+ | Metric | Strategy |
300
+ |--------|----------|
301
+ | `steps` | Source priority: `device > app > unknown > manual_input`, then deterministic single-winner tie-break for same-priority overlaps |
302
+ | `activetimes`, `calories`, `distances` | Proportional-by-time allocation |
303
+
304
+ Bucketized results preserve requested `hourly`/`daily` boundaries and do not merge across bucket edges.
305
+
306
+ ### Trust & Fallback Notes
307
+
308
+ - `manual_input` with identifiable device metadata is accepted as `low_confidence`.
309
+ - `manual_input` remains the lowest source priority in overlap resolution.
310
+ - `total - basal` fallback is applied only to uncovered windows (gap-fill only); direct active-calorie windows are preserved.
311
+ - Manual-derived movement evidence is excluded from fallback gate checks.
312
+
313
+ ---
314
+
315
+ ## Integrity & Warnings
316
+
317
+ `data.warnings` is an optional string array that appears when non-fatal anomalies are detected (e.g. value sanitization or boundary guard signals).
318
+
319
+ `data.integrity` is always present and describes the projection audit:
320
+
321
+ ```ts
322
+ {
323
+ projectionPreserved: boolean; // true if totals were preserved after overlap correction
324
+ roundingScale: number; // rounding precision applied
325
+ }
326
+ ```
327
+
328
+ React Native UI pattern (non-blocking):
329
+
330
+ ```tsx
331
+ const hasWarnings = !!data.warnings?.length;
332
+
333
+ return (
334
+ <View>
335
+ {hasWarnings && <Text>Data warnings available</Text>}
336
+ <Text>{`Projection preserved: ${data.integrity?.projectionPreserved}`}</Text>
337
+ </View>
338
+ );
339
+ ```
340
+
341
+ ---
342
+
343
+ ## Full Example
344
+
345
+ ```ts
346
+ import { connect, getExerciseData, setAllowDatasource } from '@cariva/exercise-sdk';
347
+
348
+ async function loadHealthData() {
349
+ // Exclude manual entries
350
+ await setAllowDatasource({ blacklist: ['manual_input'] });
351
+
352
+ // Connect with minimal permission scope
353
+ const status = await connect({
354
+ onMissingApp: 'status',
355
+ requestPermission: true,
356
+ permissionScope: ['steps', 'calories'],
357
+ });
358
+
359
+ if (!status.ready) {
360
+ console.warn('Health Connect not ready. Next action:', status.nextAction);
361
+ return null;
362
+ }
363
+
364
+ // Query last 24 hours in hourly buckets
365
+ const data = await getExerciseData({
366
+ sinceMillis: Date.now() - 24 * 60 * 60 * 1000,
367
+ untilMillis: Date.now(),
368
+ type: 'all',
369
+ bucketPeriod: 'hourly',
370
+ });
371
+
372
+ return data;
373
+ }
374
+ ```
@@ -0,0 +1,66 @@
1
+ buildscript {
2
+ ext.CarivaExerciseSdk = [
3
+ kotlinVersion: "2.0.21",
4
+ minSdkVersion: 24,
5
+ compileSdkVersion: 36,
6
+ targetSdkVersion: 36
7
+ ]
8
+
9
+ ext.getExtOrDefault = { prop ->
10
+ if (rootProject.ext.has(prop)) {
11
+ return rootProject.ext.get(prop)
12
+ }
13
+
14
+ return CarivaExerciseSdk[prop]
15
+ }
16
+
17
+ repositories {
18
+ google()
19
+ mavenCentral()
20
+ }
21
+
22
+ dependencies {
23
+ classpath "com.android.tools.build:gradle:8.7.2"
24
+ // noinspection DifferentKotlinGradleVersion
25
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${getExtOrDefault('kotlinVersion')}"
26
+ }
27
+ }
28
+
29
+
30
+ apply plugin: "com.android.library"
31
+ apply plugin: "kotlin-android"
32
+
33
+ apply plugin: "com.facebook.react"
34
+
35
+ android {
36
+ namespace "com.carivaexercisesdk"
37
+
38
+ compileSdkVersion getExtOrDefault("compileSdkVersion")
39
+
40
+ defaultConfig {
41
+ minSdkVersion getExtOrDefault("minSdkVersion")
42
+ targetSdkVersion getExtOrDefault("targetSdkVersion")
43
+ }
44
+
45
+ buildTypes {
46
+ release {
47
+ minifyEnabled false
48
+ }
49
+ }
50
+
51
+ lint {
52
+ disable "GradleCompatible"
53
+ }
54
+
55
+ compileOptions {
56
+ sourceCompatibility JavaVersion.VERSION_1_8
57
+ targetCompatibility JavaVersion.VERSION_1_8
58
+ }
59
+ }
60
+
61
+ dependencies {
62
+ implementation "com.facebook.react:react-android"
63
+ implementation "androidx.health.connect:connect-client:1.1.0-alpha10"
64
+ implementation "androidx.activity:activity-ktx:1.9.3"
65
+ testImplementation "junit:junit:4.13.2"
66
+ }
@@ -0,0 +1,40 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
+ <uses-permission android:name="android.permission.health.READ_ACTIVE_CALORIES_BURNED" />
3
+ <uses-permission android:name="android.permission.health.READ_TOTAL_CALORIES_BURNED" />
4
+ <uses-permission android:name="android.permission.health.READ_BASAL_METABOLIC_RATE" />
5
+ <uses-permission android:name="android.permission.health.READ_STEPS" />
6
+ <uses-permission android:name="android.permission.health.READ_DISTANCE" />
7
+ <uses-permission android:name="android.permission.health.READ_EXERCISE" />
8
+
9
+ <uses-permission android:name="androidx.health.permission.ACTIVE_CALORIES_BURNED_READ" />
10
+ <uses-permission android:name="androidx.health.permission.TOTAL_CALORIES_BURNED_READ" />
11
+ <uses-permission android:name="androidx.health.permission.BASAL_METABOLIC_RATE_READ" />
12
+ <uses-permission android:name="androidx.health.permission.STEPS_READ" />
13
+ <uses-permission android:name="androidx.health.permission.DISTANCE_READ" />
14
+ <uses-permission android:name="androidx.health.permission.EXERCISE_READ" />
15
+
16
+ <queries>
17
+ <package android:name="com.google.android.apps.healthdata" />
18
+ <package android:name="com.google.android.healthconnect.controller" />
19
+ </queries>
20
+
21
+ <application>
22
+ <activity
23
+ android:name=".HealthConnectPermissionsRationaleActivity"
24
+ android:exported="true">
25
+ <intent-filter>
26
+ <action android:name="androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE" />
27
+ </intent-filter>
28
+ </activity>
29
+
30
+ <activity
31
+ android:name=".HealthConnectPermissionUsageActivity"
32
+ android:exported="true"
33
+ android:permission="android.permission.START_VIEW_PERMISSION_USAGE">
34
+ <intent-filter>
35
+ <action android:name="android.intent.action.VIEW_PERMISSION_USAGE" />
36
+ <category android:name="android.intent.category.HEALTH_PERMISSIONS" />
37
+ </intent-filter>
38
+ </activity>
39
+ </application>
40
+ </manifest>
@@ -0,0 +1,30 @@
1
+ package com.carivaexercisesdk
2
+
3
+ import com.facebook.react.BaseReactPackage
4
+ import com.facebook.react.bridge.NativeModule
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.module.model.ReactModuleInfo
7
+ import com.facebook.react.module.model.ReactModuleInfoProvider
8
+
9
+ class CarivaExerciseSdkPackage : BaseReactPackage() {
10
+ override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
11
+ return when (name) {
12
+ HealthConnectModule.NAME -> HealthConnectModule(reactContext)
13
+ else -> null
14
+ }
15
+ }
16
+
17
+ override fun getReactModuleInfoProvider() = ReactModuleInfoProvider {
18
+ mapOf(
19
+ HealthConnectModule.NAME to
20
+ ReactModuleInfo(
21
+ name = HealthConnectModule.NAME,
22
+ className = HealthConnectModule.NAME,
23
+ canOverrideExistingModule = false,
24
+ needsEagerInit = false,
25
+ isCxxModule = false,
26
+ isTurboModule = false
27
+ )
28
+ )
29
+ }
30
+ }