Skip to content

Commit d00d2fc

Browse files
committed
#3-trimmer workaround for WriteHealthData
1 parent 469a1da commit d00d2fc

3 files changed

Lines changed: 83 additions & 65 deletions

File tree

src/Maui.Health/Maui.Health.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
<DebugType>embedded</DebugType>
4343
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
4444
<EmbedAllSources>true</EmbedAllSources>
45-
<Version>2.0.0-preview13</Version>
45+
<Version>2.0.0-preview14</Version>
4646
<PackageReleaseNotes>Added trimmer workaround from @osyyyS</PackageReleaseNotes>
4747
</PropertyGroup>
4848

src/Maui.Health/Platforms/Android/HealthServiceAndroid.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,15 @@ private async Task<List<TDto>> GetHealthDataInternal<TDto>(HealthTimeRange timeR
165165
}
166166
}
167167

168-
public async partial Task<bool> WriteHealthData<TDto>(TDto data, CancellationToken cancellationToken) where TDto : HealthMetricBase
168+
//https://github.com/Kebechet/Maui.Health/pull/8/files
169+
//Split to `public partial` and `private async` method because of trimmer/linker issue
170+
public partial Task<bool> WriteHealthData<TDto>(TDto data, CancellationToken cancellationToken)
171+
where TDto : HealthMetricBase
172+
{
173+
return WriteHealthDataInternal(data, cancellationToken);
174+
}
175+
176+
private async Task<bool> WriteHealthDataInternal<TDto>(TDto data, CancellationToken cancellationToken) where TDto : HealthMetricBase
169177
{
170178
try
171179
{
@@ -211,5 +219,6 @@ public async partial Task<bool> WriteHealthData<TDto>(TDto data, CancellationTok
211219
return false;
212220
}
213221
}
222+
214223
private Result<SdkCheckError> IsSdkAvailable() => JavaReflectionHelper.CheckSdkAvailability(_activityContext);
215224
}

src/Maui.Health/Platforms/iOS/HealthServiceiOS.cs

Lines changed: 72 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,76 @@ [new NSSortDescriptor(HKSample.SortIdentifierStartDate, false)],
214214
}
215215
}
216216

217+
//https://github.com/Kebechet/Maui.Health/pull/8/files
218+
//Split to `public partial` and `private async` method because of trimmer/linker issue
219+
public partial Task<bool> WriteHealthData<TDto>(TDto data, CancellationToken cancellationToken)
220+
where TDto : HealthMetricBase
221+
{
222+
return WriteHealthDataInternal(data, cancellationToken);
223+
}
224+
225+
private async Task<bool> WriteHealthDataInternal<TDto>(TDto data, CancellationToken cancellationToken)
226+
where TDto : HealthMetricBase
227+
{
228+
if (!IsSupported)
229+
{
230+
return false;
231+
}
232+
233+
try
234+
{
235+
_logger.LogInformation("iOS WriteHealthDataAsync<{DtoName}>", typeof(TDto).Name);
236+
237+
// Request write permission for the specific metric
238+
var readPermission = MetricDtoExtensions.GetRequiredPermission<TDto>();
239+
var writePermission = new HealthPermissionDto
240+
{
241+
HealthDataType = readPermission.HealthDataType,
242+
PermissionType = PermissionType.Write
243+
};
244+
var permissionResult = await RequestPermissions([writePermission], cancellationToken: cancellationToken);
245+
if (!permissionResult.IsSuccess)
246+
{
247+
_logger.LogWarning("iOS Write: Permission denied for {DtoName}", typeof(TDto).Name);
248+
return false;
249+
}
250+
251+
// Convert DTO to HKObject (HKQuantitySample or HKWorkout)
252+
HKObject? sample = data.ToHKObject();
253+
if (sample == null)
254+
{
255+
_logger.LogWarning("iOS Write: Failed to convert {DtoName} to HKObject", typeof(TDto).Name);
256+
return false;
257+
}
258+
259+
// Save to HealthKit
260+
using var healthStore = new HKHealthStore();
261+
var tcs = new TaskCompletionSource<bool>();
262+
263+
healthStore.SaveObject(sample, (success, error) =>
264+
{
265+
if (error != null)
266+
{
267+
_logger.LogError("iOS Write Error: {Error}", error.LocalizedDescription);
268+
tcs.TrySetResult(false);
269+
}
270+
else
271+
{
272+
_logger.LogInformation("iOS Write: Successfully wrote {DtoName}", typeof(TDto).Name);
273+
tcs.TrySetResult(success);
274+
}
275+
});
276+
277+
using var ct = cancellationToken.Register(() => tcs.TrySetCanceled());
278+
return await tcs.Task;
279+
}
280+
catch (Exception ex)
281+
{
282+
_logger.LogError(ex, "iOS Write Exception for {DtoName}", typeof(TDto).Name);
283+
return false;
284+
}
285+
}
286+
217287
private static bool IsCumulativeType<TDto>() where TDto : HealthMetricBase
218288
{
219289
return typeof(TDto) == typeof(StepsDto) ||
@@ -225,7 +295,8 @@ private async Task<List<TDto>> GetCumulativeHealthDataAsync<TDto>(
225295
NSPredicate predicate,
226296
HealthTimeRange timeRange,
227297
HealthDataType healthDataType,
228-
CancellationToken cancellationToken) where TDto : HealthMetricBase
298+
CancellationToken cancellationToken)
299+
where TDto : HealthMetricBase
229300
{
230301
var tcs = new TaskCompletionSource<TDto[]>();
231302

@@ -299,66 +370,4 @@ private async Task<List<TDto>> GetCumulativeHealthDataAsync<TDto>(
299370

300371
return results.ToList();
301372
}
302-
303-
public async partial Task<bool> WriteHealthData<TDto>(TDto data, CancellationToken cancellationToken) where TDto : HealthMetricBase
304-
{
305-
if (!IsSupported)
306-
{
307-
return false;
308-
}
309-
310-
try
311-
{
312-
_logger.LogInformation("iOS WriteHealthDataAsync<{DtoName}>", typeof(TDto).Name);
313-
314-
// Request write permission for the specific metric
315-
var readPermission = MetricDtoExtensions.GetRequiredPermission<TDto>();
316-
var writePermission = new HealthPermissionDto
317-
{
318-
HealthDataType = readPermission.HealthDataType,
319-
PermissionType = PermissionType.Write
320-
};
321-
var permissionResult = await RequestPermissions([writePermission], cancellationToken: cancellationToken);
322-
if (!permissionResult.IsSuccess)
323-
{
324-
_logger.LogWarning("iOS Write: Permission denied for {DtoName}", typeof(TDto).Name);
325-
return false;
326-
}
327-
328-
// Convert DTO to HKObject (HKQuantitySample or HKWorkout)
329-
HKObject? sample = data.ToHKObject();
330-
if (sample == null)
331-
{
332-
_logger.LogWarning("iOS Write: Failed to convert {DtoName} to HKObject", typeof(TDto).Name);
333-
return false;
334-
}
335-
336-
// Save to HealthKit
337-
using var healthStore = new HKHealthStore();
338-
var tcs = new TaskCompletionSource<bool>();
339-
340-
healthStore.SaveObject(sample, (success, error) =>
341-
{
342-
if (error != null)
343-
{
344-
_logger.LogError("iOS Write Error: {Error}", error.LocalizedDescription);
345-
tcs.TrySetResult(false);
346-
}
347-
else
348-
{
349-
_logger.LogInformation("iOS Write: Successfully wrote {DtoName}", typeof(TDto).Name);
350-
tcs.TrySetResult(success);
351-
}
352-
});
353-
354-
using var ct = cancellationToken.Register(() => tcs.TrySetCanceled());
355-
return await tcs.Task;
356-
}
357-
catch (Exception ex)
358-
{
359-
_logger.LogError(ex, "iOS Write Exception for {DtoName}", typeof(TDto).Name);
360-
return false;
361-
}
362-
}
363-
364373
}

0 commit comments

Comments
 (0)