Deleting data Remove health data by type and time range, by UUID on iOS or by client record ID on Android.
The Health class provides three delete methods. Deleting requires WRITE permission for the type; see Permissions .
Delete by type and interval:
await health . delete (
type : HealthDataType . STEPS ,
startTime : start ,
endTime : end ,
) ;
Delete a specific record by UUID:
await health . deleteByUUID (
uuid : 'A91A2F10-3D7B-486A-B140-5ADCD3C9C6D0' ,
type : HealthDataType . WORKOUT , // required on iOS
) ;
Delete by client record ID (Android Health Connect):
await health . deleteByClientRecordId (
dataTypeKey : HealthDataType . ACTIVE_ENERGY_BURNED ,
clientRecordId : 'my-id-1' ,
) ;
delete removes all data of a type within a time period.
Future < bool > delete ({
required HealthDataType type ,
required DateTime startTime ,
required DateTime endTime ,
})
// Delete today's steps
final today = DateTime . now () ;
final startOfDay = DateTime (today . year , today . month , today . day) ;
await health . delete (
type : HealthDataType . STEPS ,
startTime : startOfDay ,
endTime : today ,
) ;
// Delete weight measurements from last week
await health . delete (
type : HealthDataType . WEIGHT ,
startTime : DateTime . now () . subtract ( Duration (days : 7 )) ,
endTime : DateTime . now () ,
) ;
Future < bool > deleteDay ( HealthDataType type , DateTime date) async {
final startOfDay = DateTime (date . year , date . month , date . day) ;
final endOfDay = startOfDay . add ( Duration (days : 1 )) ;
return await health . delete (
type : type ,
startTime : startOfDay ,
endTime : endOfDay ,
) ;
}
// Usage
await deleteDay ( HealthDataType . HEART_RATE , DateTime . now ()) ;
Future < bool > deleteAllData ( HealthDataType type) async {
// Delete from a very old date to now
return await health . delete (
type : type ,
startTime : DateTime ( 2000 , 1 , 1 ) ,
endTime : DateTime . now () ,
) ;
}
// Usage
await deleteAllData ( HealthDataType . STEPS ) ;
deleteByUUID deletes a specific data point by its unique identifier. Read the data first to get the point's uuid; see Data points .
Future < bool > deleteByUUID ({
required String uuid ,
})
deleteByUUID also takes an optional type (HealthDataType), which iOS requires. Pass the type of the data point, as in the quick reference .
// First, get the data with UUID
final dataPoints = await health . getHealthDataFromTypes (
types : [ HealthDataType . WEIGHT ] ,
startDate : DateTime . now () . subtract ( Duration (days : 7 )) ,
endDate : DateTime . now () ,
) ;
// Delete a specific point
if (dataPoints . isNotEmpty) {
final uuid = dataPoints . first . uuid ;
final success = await health . deleteByUUID (uuid : uuid) ;
if (success) {
print ( 'Data point deleted' ) ;
}
}
class DataPointManager {
final Health health ;
DataPointManager ( this . health) ;
Future < bool > deleteReading ( HealthDataPoint point) async {
if (point . uuid . isEmpty) {
print ( 'No UUID available' ) ;
return false ;
}
return await health . deleteByUUID (uuid : point . uuid) ;
}
Future < int > deleteMultipleReadings ( List < HealthDataPoint > points) async {
int deletedCount = 0 ;
for ( var point in points) {
if (point . uuid . isNotEmpty) {
final success = await health . deleteByUUID (uuid : point . uuid) ;
if (success) deletedCount ++;
}
}
return deletedCount ;
}
}
// Usage
final manager = DataPointManager (health) ;
await manager . deleteReading (dataPoint) ;
deleteByClientRecordId deletes data by a custom record identifier on Health Connect.
Future < bool > deleteByClientRecordId ({
required String clientRecordId ,
})
deleteByClientRecordId also takes the data type as dataTypeKey (HealthDataType), as in the quick reference .
// Delete by custom record ID
await health . deleteByClientRecordId (
clientRecordId : 'my-app-weight-2024-01-15' ,
) ;
Generate a custom ID when you write the data, then delete by the same ID later. For a write method that accepts a client record ID, see the writeBloodPressure example in Writing data .
class RecordIdGenerator {
static String generate ( HealthDataType type , DateTime timestamp) {
final dateStr = timestamp . toIso8601String () ;
return 'myapp_ ${ type . name } _ $ dateStr ' ;
}
}
// When writing data, use custom ID
final recordId = RecordIdGenerator . generate (
HealthDataType . WEIGHT ,
DateTime . now () ,
) ;
// Later, delete by this ID
await health . deleteByClientRecordId (clientRecordId : recordId) ;
class BulkDeleteManager {
final Health health ;
BulkDeleteManager ( this . health) ;
Future < Map < HealthDataType , bool >> deleteMultipleTypes ({
required List < HealthDataType > types ,
required DateTime startTime ,
required DateTime endTime ,
}) async {
final results = < HealthDataType , bool > {} ;
for ( var type in types) {
final success = await health . delete (
type : type ,
startTime : startTime ,
endTime : endTime ,
) ;
results[type] = success ;
}
return results ;
}
Future < void > clearAllActivityData ( DateTime date) async {
final activityTypes = [
HealthDataType . STEPS ,
HealthDataType . DISTANCE_WALKING_RUNNING ,
HealthDataType . ACTIVE_ENERGY_BURNED ,
HealthDataType . FLIGHTS_CLIMBED ,
] ;
final startOfDay = DateTime (date . year , date . month , date . day) ;
final endOfDay = startOfDay . add ( Duration (days : 1 )) ;
final results = await deleteMultipleTypes (
types : activityTypes ,
startTime : startOfDay ,
endTime : endOfDay ,
) ;
results . forEach ((type , success) {
print ( ' ${ type . name } : ${ success ? "✓" : "✗" } ' ) ;
}) ;
}
}
// Usage
final manager = BulkDeleteManager (health) ;
await manager . clearAllActivityData ( DateTime . now ()) ;
Read the data, then delete only the points that match a condition:
class SelectiveDeleter {
final Health health ;
SelectiveDeleter ( this . health) ;
// Delete outliers (e.g., unrealistic values)
Future < int > deleteOutliers ({
required HealthDataType type ,
required DateTime startDate ,
required DateTime endDate ,
required bool Function ( HealthDataPoint ) isOutlier ,
}) async {
// Read data
final dataPoints = await health . getHealthDataFromTypes (
types : [type] ,
startDate : startDate ,
endDate : endDate ,
) ;
int deletedCount = 0 ;
// Delete outliers
for ( var point in dataPoints) {
if ( isOutlier (point) && point . uuid . isNotEmpty) {
final success = await health . deleteByUUID (uuid : point . uuid) ;
if (success) deletedCount ++;
}
}
return deletedCount ;
}
}
// Usage
final deleter = SelectiveDeleter (health) ;
final deletedCount = await deleter . deleteOutliers (
type : HealthDataType . WEIGHT ,
startDate : DateTime . now () . subtract ( Duration (days : 30 )) ,
endDate : DateTime . now () ,
isOutlier : (point) {
final value = (point . value as NumericHealthValue ) . numericValue ;
// Delete weights outside reasonable range
return value < 30 || value > 300 ;
} ,
) ;
print ( 'Deleted $ deletedCount outlier readings' ) ;
Count the affected data points and ask the user to confirm before you delete:
Future < bool > safeDelete ({
required Health health ,
required HealthDataType type ,
required DateTime startTime ,
required DateTime endTime ,
required Future < bool > Function ( int count) confirmDeletion ,
}) async {
// First, count how many data points will be deleted
final dataPoints = await health . getHealthDataFromTypes (
types : [type] ,
startDate : startTime ,
endDate : endTime ,
) ;
if (dataPoints . isEmpty) {
print ( 'No data to delete' ) ;
return false ;
}
// Ask for confirmation
final confirmed = await confirmDeletion (dataPoints . length) ;
if ( ! confirmed) {
print ( 'Deletion cancelled' ) ;
return false ;
}
// Proceed with deletion
return await health . delete (
type : type ,
startTime : startTime ,
endTime : endTime ,
) ;
}
// Usage
await safeDelete (
health : health ,
type : HealthDataType . STEPS ,
startTime : startDate ,
endTime : endDate ,
confirmDeletion : (count) async {
print ( 'About to delete $ count data points' ) ;
// In real app, show a dialog
return true ; // User confirmed
} ,
) ;
Android iOS
Supports delete and deleteByClientRecordId.
Time-range deletion may affect data from other apps.
Custom record IDs enable precise deletion.
Requires WRITE permission.
Check Health Connect availability first; see Health Connect .
Supports delete and deleteByUUID.
UUID-based deletion is precise.
Deletion is immediate and cannot be undone.
May affect data in other apps.
A delete returns false when it fails, for example because permission is missing or there is no data:
Future < void > deleteWithErrorHandling (
HealthDataType type ,
DateTime start ,
DateTime end ,
) async {
try {
final success = await health . delete (
type : type ,
startTime : start ,
endTime : end ,
) ;
if (success) {
print ( '✓ Data deleted successfully' ) ;
} else {
print ( '✗ Deletion failed' ) ;
print ( ' Check permissions or data existence' ) ;
}
} catch (e) {
print ( '✗ Error during deletion: $ e ' ) ;
}
}
Deletion requires WRITE permission:
final types = [ HealthDataType . STEPS , HealthDataType . WEIGHT ] ;
final granted = await health . requestAuthorization (
types ,
permissions : List . filled (types . length , HealthDataAccess . WRITE ) ,
) ;
if (granted) {
// Can now delete data
await health . delete (
type : HealthDataType . STEPS ,
startTime : startTime ,
endTime : endTime ,
) ;
}
For managing permissions, see Permissions .