cph-cachet / flutter-plugins

A collection of Flutter plugins developed by CACHET
548 stars 660 forks source link

Health 3.4.3 - iOS error when writing BMI value - could not cast value of type 'HKQuantitytype' - possible solution included #500

Closed samflink closed 2 years ago

samflink commented 2 years ago

Device / Emulator and OS

Describe the bug

Heads up: I've found the problem and included a proposal for the solution under: Additional information / possible solution

I attempt to write the BMI data as follows:

double _bmiResult = 22.9;
success = await health.writeHealthData(
            _bmiResult, HealthDataType.BODY_MASS_INDEX, earlier, now);

After calling writeHealthData the app crashes with this error : _Successfully called writeData with value of 22.9 and type of BODY_MASSINDEX

_Could not cast value of type 'HKQuantityType' (0x1e9536f68) to 'HKCategoryType' (0x1e9536f90). Could not cast value of type 'HKQuantityType' (0x1e9536f68) to 'HKCategoryType' (0x1e9536f90).

To Reproduce

  1. use the example app provided with Health 3.4.3
  2. Add this function:
Future addDataBmiExample() async {
    final now = DateTime.now();
    final earlier = now.subtract(Duration(minutes: 5));

    final types = [HealthDataType.BODY_MASS_INDEX];
    final rights = [HealthDataAccess.WRITE];
    final permissions = [HealthDataAccess.READ_WRITE];
    bool? hasPermissions =
    await HealthFactory.hasPermissions(types, permissions: rights);
    if (hasPermissions == false) {
      await health.requestAuthorization(types, permissions: permissions);
    }

      bool success = await health.writeHealthData(
           _bmiResult, HealthDataType.BODY_MASS_INDEX, earlier, now);

      setState(() {
        _state = success ? AppState.DATA_ADDED : AppState.DATA_NOT_ADDED;
      });
  }
  1. replace the onPressed() function
    IconButton(
                onPressed: () {
                  //addData();
                  addDataBmiExample();
                },
                icon: Icon(Icons.add),
              ),

Expected behavior

I expect that the BMI data saved is correctly and most of all that the app does not crash :)

Actual behavior

The app crashes and the BMI data is not saved.

Screenshots

not available

Flutter doctor

[✓] Flutter (Channel stable, 2.8.1, on macOS 12.1 21C52 darwin-x64, locale en-NL) [✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0) [✓] Xcode - develop for iOS and macOS (Xcode 13.2.1) [✓] Chrome - develop for the web [✓] Android Studio (version 2020.3) [✓] VS Code (version 1.63.2) [✓] Connected device (3 available) • No issues found!

Additional information / possible solution

I've done some searching to track down the problem. The problem is caused by the SwiftHealthPlugin.swift location: health-3.4.3/ios/Classes/SwithHealthPlugin.swift

I suspect the problem is caused by an invalid cast caused by these pieces of code: line 194˜196:

if (unitLookUp(key: type) == HKUnit.init(from: "")) {
          sample = HKCategorySample(type: dataTypeLookUp(key: type) as! HKCategoryType, value: Int(value), start: dateFrom, end: dateTo)
        }

and line 369: unitDict[BODY_MASS_INDEX] = HKUnit.init(from: "")

The problem is caused by the handling of (""). I used this as reference: https://developer.apple.com/documentation/healthkit/hkunit/1615733-init

and changed it to: unitDict[BODY_MASS_INDEX] = HKUnit.init(from: "count")

With that adjustment the BMI data is written successful and the app does not crash anymore.

Please note that the same issue also applies to:

       unitDict[MINDFULNESS] = HKUnit.init(from: "")
        unitDict[SLEEP_IN_BED] = HKUnit.init(from: "")
        unitDict[SLEEP_ASLEEP] = HKUnit.init(from: "")
        unitDict[SLEEP_AWAKE] = HKUnit.init(from: "")
        unitDict[WORKOUT] = HKUnit.init(from: "")

Best regards,

Sam

MadsVSChristensen commented 2 years ago

Hey @samflink

Thank you for noticing and letting us know about this bug.

I have looked into it and corrected the bug. It will be released with the upcoming release.

The issue could indeed be corrected by using count however, Mindfulness, Sleep and Workout remain HKUnit.init(from: "") as the issue was the unit handling and not the unit type.

Best Regards, Mads