Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions packages/health/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,22 @@ flutter: Health Plugin Error:
flutter: PlatformException(FlutterHealth, Results are null, Optional(Error Domain=com.apple.healthkit Code=6 "Protected health data is inaccessible" UserInfo={NSLocalizedDescription=Protected health data is inaccessible}))
```

### Fetch single health data by UUID

In order to retrieve a single record, it is required to provide `String uuid` and `HealthDataType type`.

Please see example below:
```dart
HealthDataPoint? healthPoint = await health.getHealthDataByUUID(
uuid: 'random-uuid-string',
type: HealthDataType.STEPS,
);
```
```
I/FLUTTER_HEALTH( 9161): Success: {uuid=random-uuid-string, value=12, date_from=1742259061009, date_to=1742259092888, source_id=, source_name=com.google.android.apps.fitness, recording_method=0}
```
> Assuming that the `uuid` and `type` are coming from your database.

### Filtering by recording method

Google Health Connect and Apple HealthKit both provide ways to distinguish samples collected "automatically" and manually entered data by the user.
Expand Down Expand Up @@ -322,6 +338,43 @@ Furthermore, the plugin now exposes three new functions to help you check and re
2. `isHealthDataInBackgroundAuthorized()`: Checks the current status of the Health Data in Background permission
3. `requestHealthDataInBackgroundAuthorization()`: Requests the Health Data in Background permission.

### Fetch single health data by UUID

In order to retrieve a single record, it is required to provide `String uuid` and `HealthDataType type`.

Please see example below:
```dart
HealthDataPoint? healthPoint = await health.getHealthDataByUUID(
uuid: 'E9F2EEAD-8FC5-4CE5-9FF5-7C4E535FB8B8',
type: HealthDataType.WORKOUT,
);
```
```
data by UUID: HealthDataPoint -
uuid: E9F2EEAD-8FC5-4CE5-9FF5-7C4E535FB8B8,
value: WorkoutHealthValue - workoutActivityType: RUNNING,
totalEnergyBurned: null,
totalEnergyBurnedUnit: KILOCALORIE,
totalDistance: 2400,
totalDistanceUnit: METER
totalSteps: null,
totalStepsUnit: null,
unit: NO_UNIT,
dateFrom: 2025-05-02 07:31:00.000,
dateTo: 2025-05-02 08:25:00.000,
dataType: WORKOUT,
platform: HealthPlatformType.appleHealth,
deviceId: unknown,
sourceId: com.apple.Health,
sourceName: Health
recordingMethod: RecordingMethod.manual
workoutSummary: WorkoutSummary - workoutType: runningtotalDistance: 2400, totalEnergyBurned: 0, totalSteps: 0
metadata: null
deviceModel: null
```
> Assuming that the `uuid` and `type` are coming from your database.


## Data Types

The plugin supports the following [`HealthDataType`](https://pub.dev/documentation/health/latest/health/HealthDataType.html).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.util.Log
import androidx.health.connect.client.HealthConnectClient
import androidx.health.connect.client.records.*
import androidx.health.connect.client.records.metadata.Metadata
import androidx.health.connect.client.response.InsertRecordsResponse
import androidx.health.connect.client.units.*
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel.Result
Expand Down Expand Up @@ -43,17 +44,31 @@ class HealthDataWriter(
val record = createRecord(type, startTime, endTime, value, recordingMethod)

if (record == null) {
result.success(false)
result.success("")
return
}

scope.launch {
try {
healthConnectClient.insertRecords(listOf(record))
result.success(true)
// Insert records into Health Connect
val insertResponse: InsertRecordsResponse = healthConnectClient.insertRecords(listOf(record))

// Extract UUID from the first inserted record
val insertedUUID = insertResponse.recordIdsList.firstOrNull() ?: ""

if (insertedUUID.isEmpty()) {
Log.e("FLUTTER_HEALTH::ERROR", "UUID is empty! No records were inserted.")
} else {
Log.i(
"FLUTTER_HEALTH::SUCCESS",
"[Health Connect] Workout $insertedUUID was successfully added!"
)
}

result.success(insertedUUID)
} catch (e: Exception) {
Log.e("FLUTTER_HEALTH::ERROR", "Error writing $type: ${e.message}")
result.success(false)
result.success("")
}
}
}
Expand All @@ -76,7 +91,7 @@ class HealthDataWriter(
val recordingMethod = call.argument<Int>("recordingMethod")!!

if (!HealthConstants.workoutTypeMap.containsKey(type)) {
result.success(false)
result.success("")
Log.w(
"FLUTTER_HEALTH::ERROR",
"[Health Connect] Workout type not supported"
Expand Down Expand Up @@ -138,20 +153,30 @@ class HealthDataWriter(
)
}

healthConnectClient.insertRecords(list)
result.success(true)
// Insert records into Health Connect
val insertResponse: InsertRecordsResponse = healthConnectClient.insertRecords(list)

// Extract UUID from the first inserted record
val insertedUUID = insertResponse.recordIdsList.firstOrNull() ?: ""

if (insertedUUID.isEmpty()) {
Log.e("FLUTTER_HEALTH::ERROR", "UUID is empty! No records were inserted.")
}

Log.i(
"FLUTTER_HEALTH::SUCCESS",
"[Health Connect] Workout was successfully added!"
"[Health Connect] Workout $insertedUUID was successfully added!"
)

result.success(insertedUUID)
} catch (e: Exception) {
Log.w(
"FLUTTER_HEALTH::ERROR",
"[Health Connect] There was an error adding the workout",
)
Log.w("FLUTTER_HEALTH::ERROR", e.message ?: "unknown error")
Log.w("FLUTTER_HEALTH::ERROR", e.stackTrace.toString())
result.success(false)
result.success("")
}
}
}
Expand Down
Loading