Search Unity

BEHealthKit: HealthKit plugin for Unity iOS

Discussion in 'Assets and Asset Store' started by beliefengine, Mar 20, 2020.

  1. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    38
    There is always going to be some delay with ReadQuantitySamples, especially with steps because they're grouped in batches, but you shouldn't have to switch to another app.

    If you want closer to live reporting, I'd suggest looking into the Pedometer methods; if that doesn't do it, I'd need to see some code to try and troubleshoot.
     
  2. cancelself

    cancelself

    Joined:
    May 30, 2015
    Posts:
    4
    Hi. Good work so far, but getting an error with the HRV quantity sample. Can likely workaround with some changes to your source on my side, but if you have a fix, would love to use it.


    double ReadHRVData()

    {



    Debug.Log("Reading HRV Data");



    DateTimeOffset now = DateTimeOffset.UtcNow;

    DateTimeOffset start = now.AddDays(-1);


    this.healthStore.ReadQuantitySamples(HKDataType.HKQuantityTypeIdentifierHeartRateVariabilitySDNN, start, now, delegate (List<QuantitySample> samples, Error error) {

    this.Hrv = samples.Count;

    });


    return 0.0;


    }



    2021-09-21 11:37:08.236440-0700 nrsh[51507:4350643] Uncaught exception: NSInvalidArgumentException: Attempt to convert incompatible units: ms, ()

    (

    0 CoreFoundation 0x0000000183744070 6174789A-E88C-3F5C-BA39-DE2E9EDC0750 + 626800

    1 libobjc.A.dylib 0x000000019bc5ef54 objc_exception_throw + 60

    2 CoreFoundation 0x000000018379b190 6174789A-E88C-3F5C-BA39-DE2E9EDC0750 + 983440

    3 HealthKit 0x00000001900870e8 1BA6AE73-3187-30DC-A267-80492F1B5A16 + 16616

    4 HealthKit 0x0000000190087054 1BA6AE73-3187-30DC-A267-80492F1B5A16 + 16468

    5 UnityFramework 0x00000001033611c4 -[HKDiscreteQuantitySample(serialization) be_serializable] + 244

    6 UnityFramework 0x0000000103362930 +[HealthData XMLFromQuantitySamples:datatype:error:] + 352

    7 UnityFramework 0x00000001033683dc __ReadQuantity_block_invoke + 408

    8 UnityFramework 0x0000000103364d90 __64-[BEHealthKit(read) readSamples:fromDate:toDate:resultsHandler:]_block_invoke + 148

    9 libdispatch.dylib 0x00000001833b4c04 959CD6E4-0CE7-3022-B73C-8B36F79F4745 + 7172

    10 libdispatch.dylib 0x00000001833b6950 959CD6E4-0CE7-3022-B73C-8B36F79F4745 + 14672

    11 libdispatch.dylib 0x00000001833be0ac 959CD6E4-0CE7-3022-B73C-8B36F79F4745 + 45228

    12 libdispatch.dylib 0x00000001833bec44 959CD6E4-0CE7-3022-B73C-8B36F79F4745 + 48196

    13 libdispatch.dylib 0x00000001833c9318 959CD6E4-0CE7-3022-B73C-8B36F79F4745 + 90904

    14 libsystem_pthread.dylib 0x00000001f3b791b0 _pthread_wqthread + 288

    15 libsystem_pthread.dylib 0x00000001f3b78f50 start_wqthread + 8

    )
     
  3. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    38
    Ah, I'm sorry about that. The good news is it'll be a quick/easy fix, so I'll try & get something submitted today.

     
  4. cancelself

    cancelself

    Joined:
    May 30, 2015
    Posts:
    4
    Currently unblocked, with the following changes.
     

    Attached Files:

    beliefengine likes this.
  5. cancelself

    cancelself

    Joined:
    May 30, 2015
    Posts:
    4
    Also, I was using the wrong query method before, but the absence of the HKUnit for that quantity type and not passing the statistics options were still blocking.
     

    Attached Files:

  6. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    38
    Good to know. I'm currently doing a quick pass to make sure I'm not missing default units for any other quantity types, but I'll add that fix for the statistics options before I submit, which should be fairly shortly.
     
  7. cancelself

    cancelself

    Joined:
    May 30, 2015
    Posts:
    4
    Thank you for building this. Definitely work $40.00 to support your efforts here. Very important intersection between wearables/wellness and games.
     
  8. TheDreamEXE

    TheDreamEXE

    Joined:
    May 14, 2015
    Posts:
    60
    Wow incredible work! Now if only there was a Wear OS equivalent, then making a single project for both platforms would truly be less of a headache lol
     
  9. schnauzerfan

    schnauzerfan

    Joined:
    Mar 16, 2017
    Posts:
    3
    Hi there,

    I'm getting an error running the 'Full Test Scene' example scene on iPhone:

    This only seems to happen when reading the HKQuantityTypeIdentifierBodyMass data type - (steps works fine for example).

    chrome_hxLTprxcmE.png


    read data...
    HealthKitFullTest:ReadData()
    UnityEngine.Events.UnityAction:Invoke()
    UnityEngine.Events.UnityEvent:Invoke()
    UnityEngine.EventSystems.EventFunction`1:Invoke(T1, BaseEventData)
    UnityEngine.EventSystems.ExecuteEvents:Execute(GameObject, BaseEventData, EventFunction`1)
    UnityEngine.EventSystems.StandaloneInputModule:ProcessTouchPress(PointerEventData, Boolean, Boolean)
    UnityEngine.EventSystems.StandaloneInputModule:ProcessTouchEvents()
    UnityEngine.EventSystems.StandaloneInputModule:Process()
    reading quantity-type...
    HealthKitFullTest:ReadData()
    UnityEngine.Events.UnityAction:Invoke()
    UnityEngine.Events.UnityEvent:Invoke()
    UnityEngine.EventSystems.EventFunction`1:Invoke(T1, BaseEventData)
    UnityEngine.EventSystems.ExecuteEvents:Execute(GameObject, BaseEventData, EventFunction`1)
    UnityEngine.EventSystems.StandaloneInputModule:ProcessTouchPress(PointerEventData, Boolean, Boolean)
    UnityEngine.EventSystems.StandaloneInputModule:ProcessTouchEvents()
    UnityEngine.EventSystems.StandaloneInputModule:Process()
    reading HKQuantityTypeIdentifierBodyMass from 1/21/2022 8:40:45 AM +00:00 to 1/22/2022 8:40:45 AM +00:00
    HealthKitFullTest:ReadQuantityData(HKDataType, DateTimeOffset, DateTimeOffset)
    HealthKitFullTest:ReadData()
    UnityEngine.Events.UnityAction:Invoke()
    UnityEngine.Events.UnityEvent:Invoke()
    UnityEngine.EventSystems.EventFunction`1:Invoke(T1, BaseEventData)
    UnityEngine.EventSystems.ExecuteEvents:Execute(GameObject, BaseEventData, EventFunction`1)
    UnityEngine.EventSystems.StandaloneInputModule:ProcessTouchPress(PointerEventData, Boolean, Boolean)
    UnityEngine.EventSystems.StandaloneInputModule:ProcessTouchEvents()
    UnityEngine.EventSystems.StandaloneInputModule:Process()
    reading quantity from:
    -1/21/2022 8:40:45 AM +00:00 (1642754445.38841)
    to:
    -1/22/2022 8:40:45 AM +00:00 (1642840845.38841)
    BeliefEngine.HealthKit.HealthStore:ReadQuantity(HKDataType, DateTimeOffset, DateTimeOffset, Boolean)
    HealthKitFullTest:ReadQuantityData(HKDataType, DateTimeOffset, DateTimeOffset)
    HealthKitFullTest:ReadData()
    UnityEngine.Events.UnityAction:Invoke()
    UnityEngine.Events.UnityEvent:Invoke()
    UnityEngine.EventSystems.EventFunction`1:Invoke(T1, BaseEventData)
    UnityEngine.EventSystems.ExecuteEvents:Execute(GameObject, BaseEventData, EventFunction`1)
    UnityEngine.EventSystems.StandaloneInputModule:ProcessTouchPress(PointerEventData, Boolean, Boolean)
    UnityEngine.EventSystems.StandaloneInputModule:ProcessTouchEvents()
    UnityEngine.EventSystems.StandaloneInputModule:Process()
    2022-01-22 09:40:45.395902+0100 BEHealthKit[21368:575276] [reading quantity from Fri Jan 21 09:40:45 2022 to Sat Jan 22 09:40:45 2022]
    (lldb)
     
    Last edited: Jan 22, 2022
  10. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    38
    Hmm, that's strange. While there's far too many data types for me to test every release, that one in particular I've tested & re-tested just now, and it should be fine.

    A few questions to try & narrow down the source of the problem:

    1. are you using the latest BEHealthKit (1.11.3)?
    2. what version of iOS?
    3. if you have multiple test devices, does this happen on all of them?
    4. what language & region is your test device set to?
    5. did you make any changes to the package?
     
  11. schnauzerfan

    schnauzerfan

    Joined:
    Mar 16, 2017
    Posts:
    3
    1. 1.11.3 on all devices
    2. The error was throwing on iOS 12.5.5, but a newer device running 15.1 is getting body mass data properly.
    3. 2 test devices (as above)
    4. Both test devices are set to English/Australia
    5. No changes to the package - I created an empty Unity 2020.3.25f1 project with only the BEHealthKit plugin, and built the 'Full Test Scene' scene.
     
  12. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    38
    Ahh. I'm glad to hear it's working on one of your devices, at least. This is the source of the issue, though.

    The good news is, if it's what I think it is, it'll be a relatively easy fix, so I should be able to have something submitted soon. I'll have to check in the morning whether we have a device running iOS 12 lying around, but whether or not we do, but it should be pretty straightforward either way.
     
  13. schnauzerfan

    schnauzerfan

    Joined:
    Mar 16, 2017
    Posts:
    3
    Thanks so much - no need to rush ;)

    At the moment I'm just trying to determine the minimum iOS target I'll be supporting. If I know I can support an iPhone 6 (i.e. at least iOS 12) that would be great to know.
     
  14. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    38
    It wasn't a rush, but because it was just a matter of adding a couple version checks to the native code, and I did have an old iPhone 6 lying around, I was able to quickly spot-check the fix. New version is submitted!

    A word of warning – if you are planning on supporting back to iOS 12, it's probably best you limit yourself to only data types available in that version. It shouldn't crash if you request data that iOS doesn't support, with this fix, but it's not exactly designed to fail gracefully. You'll need to make sure to catch the errors returned by BEHealthKit & handle them appropriately.
     
  15. tusharko

    tusharko

    Joined:
    Apr 7, 2022
    Posts:
    1
    Hi getting these errors when trying to build for ios in xcode

    Undefined symbols for architecture arm64:
    "_OBJC_CLASS_$_HKObject", referenced from:
    __OBJC_$_CATEGORY_HKObject_$_serialization in HealthData.o
    "_OBJC_CLASS_$_HKObjectType", referenced from:
    __OBJC_$_CATEGORY_HKObjectType_$_serialization in HealthData.o
    "_OBJC_CLASS_$_HKFitzpatrickSkinTypeObject", referenced from:
    objc-class-ref in HealthData.o
    "_OBJC_CLASS_$_HKQuery", referenced from:
    objc-class-ref in BEHealthKit.o
    ...
    .
    .
     
  16. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    38
    I replied to the email you sent, but just in case it got sent to spam:

    That's a sign that the Xcode project didn't get the HealthKit capability, which is a pretty easy thing to fix. Select Unity-iPhone in the left-side navigator, then Signing & Capabilities in the center, then the "+" up top. Select HealthKit from the list.

    The build *should* have the HealthKit capability automatically added, so I'm going to have to look into why that's not happening. It could be something that changed in Unity, or Xcode, or something else. Which version of Unity & Xcode are you using?
     
    ilmario likes this.
  17. shibatom1130

    shibatom1130

    Joined:
    Mar 25, 2020
    Posts:
    6
    Hello,

    Thank you for creating this great asset.

    I have a question about step count data.

    iOS users can input step count manually via a native health care app and import step count from other third-party apps but I want to use only step count tracked by iPhone or Apple Watch.

    In native code, a developer can filter the source by using Bundle Identifier like this.

    Code (Swift):
    1. let store = HKHealthStore()
    2. let type = HKSampleType.quantityType(forIdentifier: .stepCount)!
    3. let datePredicate = HKQuery.predicateForSamples(withStart: start, end: end)
    4. let query = HKStatisticsQuery(quantityType: type,
    5.                               quantitySamplePredicate: datePredicate,
    6.                               options: .separateBySource)
    7.     { (query, data, error) in
    8.     if let sources = data?.sources?.filter({ $0.bundleIdentifier.hasPrefix("com.apple.health") }) {
    9.         let sourcesPredicate = HKQuery.predicateForObjects(from: Set(sources))
    10.         let predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [datePredicate, sourcesPredicate])
    11.         let query = HKStatisticsQuery(quantityType: type,
    12.                                       quantitySamplePredicate: predicate,
    13.                                       options: .cumulativeSum)
    14.         { (query, statistics, error) in
    15.              print(statistics?.sumQuantity())
    16.         }
    17.        store.execute(query)
    18.     }
    19. }
    20. store.execute(query)

    Can BeHealthKit asset filter step count data to use only step count tracked by iPhone or Apple Watch?
    I’d appreciate it if you would give me your answer.
     
  18. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    38
    I've begun adding limited predicate support, but I don't have quite the full rich API that native code allows, and not every native API that supports predicates has a wrapper, yet.

    If you want to limit it to just Apple devices or just one device, you could iterate through the results with something like this:

    Code (C#):
    1.  
    2. this.healthStore.ReadQuantitySamples(HKDataType.HKQuantityTypeIdentifierStepCount, start, end, delegate (List<QuantitySample> samples, Error error) {
    3.             int sum = 0;
    4.             if (samples.Count > 0) {
    5.                 foreach (QuantitySample sample in samples) {
    6.                     if (sample.source.bundleID != null && sample.source.bundleID.StartsWith("com.apple.health")) {
    7.                         sum += Convert.ToInt32(sample.quantity.doubleValue);
    8.                     }
    9.                 }
    10.             }
    11.             else {
    12.                 Debug.Log("found no samples");
    13.             }
    14.             // all done
    15.             reading = false;
    16.         });
    17.  
    (NOTE: this code, as-is, will double-count steps if the same steps are recorded by both the phone & the watch. you'd need to figure out how to merge those yourself)

    The statistics query, which I do support, unfortunately doesn't currently have all the knobs you need to achieve exactly what you want. I'll prioritize this for the next update, but I can't currently guarantee a time-frame.

    ---

    There's a workaround, though! It's a bit of a hack, but it should work with the current version of BEHealthKit. Do the above, but calculate a sum of every sample that *isn't* from an Apple device.

    Then, run a statistics query which will intelligently merge all the iPhone & Apple Watch samples, and subtract your total of whatever you want to filter out, like this:
    Code (C#):
    1.  
    2. this.healthStore.ReadStatistics(HKDataType.HKQuantityTypeIdentifierStepCount, start, end, StatisticsOptions.CumulativeSum, delegate (HealthStatistics statistics, Error error) {
    3.                 double filteredSum = statistics.sumQuantity - sum;
    4. });
    5.  
     
  19. shibatom1130

    shibatom1130

    Joined:
    Mar 25, 2020
    Posts:
    6

    Thank you for your advice and sample codes.
    I will follow your technique calculating the sum of every sample that is NOT from an Apple device for a while.
    I am looking forward to the next update on your assets!

    Thank you
     
  20. choi2022

    choi2022

    Joined:
    Jan 8, 2022
    Posts:
    4
  21. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    38
    "Authentication not determined" means that it's trying to read a data type that you haven't requested permission for.

    I'm not sure if you made any modifications to the test scene, but it's gone through *a lot* of modifications & tweaks through the versions, so it sounds like it's set up to try to read something *other* than steps. Take a look at the two test scenes; the "full" test scene script has some more examples, but if you want to read steps, something like this is one way to do it:

    Code (CSharp):
    1. healthStore.ReadQuantitySamples(HKDataType.HKQuantityTypeIdentifierStepCount, start, now, delegate(List<QuantitySample> samplesW, Error error) {
    2.     if (samplesW.Count > 0) {
    3.         foreach (QuantitySample sample in samplesW) {
    4.             Debug.Log(String.Format(" - {0} from {1} to {2}", sample.quantity.doubleValue, sample.startDate, sample.endDate));
    5.             steps += sample.quantity.doubleValue;
    6.         }
    7.             resultsLabel.text = "steps:" + steps.ToString();
    8.     }
    9. });
    10.  
     
  22. choi2022

    choi2022

    Joined:
    Jan 8, 2022
    Posts:
    4
    Does manually changing the CODE_SIGN_ENTITLEMENTS location affect it somehow also?
    I'm building the Simple Test Scene in Unity-Windows. and then zipping it, transferring it to a Mac, and then opening it and using XCode.
    I get an error on the location. its actually pointing to the location of when it was in the Windows. which is incorrect cause I'm already in the Mac. so what I did is copy the entitlement, paste it and then change the Entitlement location to the Mac.
    It seems to run, but the error still persist.
    Also I've only set to READ steps only.

    Will try your code for now.
     
  23. choi2022

    choi2022

    Joined:
    Jan 8, 2022
    Posts:
    4
    I used the Full Sample Test. it worked.. I think there is some issue in the Simple Test Scene.
     
  24. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    38
    I'll have to take a look at it in the next version; thank you for letting me know.


    No, it shouldn't matter. As long as the Xcode project is pointing to a valid entitlements file, it's perfectly fine to edit the project so that it's pointed in the right place.
     
  25. choi2022

    choi2022

    Joined:
    Jan 8, 2022
    Posts:
    4
    is there any reason why. I'm not able to get current steps data? like for example the date today is 12/7/2022.
    all I'm receiving is data's from 11/7/2022.
    At first I thought maybe there is some issue with the DateTimeOffset.
    I've already tried this:

    Code (CSharp):
    1.                 DateTimeOffset now = DateTimeOffset.UtcNow;
    2.                 //// for this example, we'll read everything from the past 24 hours
    3.                 DateTimeOffset start = now.AddDays(-1);
    4.                 DateTimeOffset aDayFromNow = now.AddDays(1);
    5.  
    6.  
    7.                     //ReadQuantityData(dataType, start, now);
    8.                     ReadQuantityData(dataType, start, aDayFromNow);

    what is this is I tried creating aDayFromNow DateTimeOffset and use that.

    so that the dates will(should) be 11/7/2022 to 13/7/2022
    The results are the same. all data's are still from 11/7/2022.
    I'm working in the Philippines if that's an issue in DateTime.
     
    Last edited: Jul 12, 2022
  26. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    38
    If you look at the logs in Xcode, you should see samples logged from "today" – I have no idea why it's not showing up in the Unity scrollview.

    But as far as I can tell by recreating it on my side, BEHK itself is working fine, and you're querying the data correctly. It's just something's wrong with how the test scene is displaying the data. I'm going to continue looking into it & will update accordingly.
     
  27. chibixi

    chibixi

    Joined:
    May 11, 2017
    Posts:
    11
    Hi @beliefengine ! I just tested both Sample Scenes - The full and the simple one and built for iOS - unfortunately when I open it on my phone, the screen is blank. I added the HealthKit capability manually and checked the XCode logs and am not sure what the issue is. I'm on an iPhone 12 and running iOS 15.6. Any ideas on what's happening? I didn't modify anything.

    upload_2022-9-5_21-52-55.png

    I see these in XCode logs
    Code (CSharp):
    1. Setting UIViewControllerBasedStatusBarAppearance to NO is no longer supported.
    2. Apple actively discourages that, and all application-wide methods of changing status bar appearance are deprecated
     
  28. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    38
    This is new to me. The Xcode log sounds like something on Unity's side – BEHealthKit doesn't have any UIViewController code in it.

    I'll check it out tomorrow, but in the meantime, what version of Unity are you using?
     
  29. chibixi

    chibixi

    Joined:
    May 11, 2017
    Posts:
    11
    Thanks for checking! The Xcode logs might be unrelated to the issue I'm seeing then. I'm on Unity 2021.3.0f1.
     
  30. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    38
    I tried it out in both 2019 and 2021; I wasn't able to reproduce it.

    The all-blue screenshot looks like a Unity build without a default scene – did you add either the Simple Test Scene or the Full Test Scene to the build?
     
  31. chibixi

    chibixi

    Joined:
    May 11, 2017
    Posts:
    11
    You're right! Clumsy mistake on my end, thanks for diving in and checking. Thanks!
     
    beliefengine likes this.
  32. ilmario

    ilmario

    Joined:
    Feb 16, 2015
    Posts:
    71
    Is healthkit now added automatically so no need to add it manually in XCode?
     
  33. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    38
    I apologize for the delay; this got buried under other projects. I've been collecting a few small fixes to put into an update, and this one in particular is tricky because it's a moving target. It works, sometimes! For some versions of Unity and Xcode, but each release has the potential to throw a wrench into that.

    I've spent yesterday & today wrapping up some loose ends for the update, and I'm currently going through the testing gauntlet. I haven't tested latest Unity yet, but this should be working again with latest Xcode in the next version.
     
    ilmario likes this.
  34. spvn

    spvn

    Joined:
    Dec 10, 2013
    Posts:
    80
    Hey before I buy this was just curious if it's been tested to work properly with iOS 16 yet? Thanks!
     
  35. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    38
    Yes, it does. I haven't updated it to support any of the new datatypes or functionality (if there is any) introduced in iOS 16, but all the basic functionality continues to work.
     
    spvn and ilmario like this.
  36. spvn

    spvn

    Joined:
    Dec 10, 2013
    Posts:
    80
    Last edited: Jan 18, 2023
  37. spvn

    spvn

    Joined:
    Dec 10, 2013
    Posts:
    80
    After looking at the documentation, it claims to support predicates for ReadStatisticsCollection. But when I check BEHealthKit+read.m, the predicate object that gets passed into the native function call is just set to nil (i.e. the predicate object I pass in isn't used at all). Can you please clarify if predicates are supported?
     
  38. spvn

    spvn

    Joined:
    Dec 10, 2013
    Posts:
    80
    Another question is what's the best way to await multiple handlers from BEHealthKit? For example if I want to read multiple statistic types (e.g. step count, calories, etc.) and update the UI only when ALL statistics have been retrieved, there doesn't seem to be an easy way to know when multiple ReadStatistic calls are done. The only way I can see is to nest the callback functions within each other (e.g. retrieve calories within the callback for retrieving step count). Any advice?

    For instance, the ideal way would be allowing me to do multiple "await" function calls. But seeing the current code I don't think that's possible.
     
  39. Aldar_Ochirov

    Aldar_Ochirov

    Joined:
    May 19, 2023
    Posts:
    2
    Hello! I encountered a problem that if we request data using the healthStore.ReadQuantitySamples method, we will receive a List<QuantitySample> that contains data from the AppleHealth log for this HKDataType. This means that data is returned to us from all sources that are connected to AppleHealth, such as the device itself, AppleWatch and others. If you sample from AppleWatch using samples.source.productType, then, as far as I understand, data loss occurs, since the data from the AppleHealth log does not correspond to the amount of sample.quantity.doubleValue for this data type. Most likely, the AppleHealth magazine generates values based on all data sources, finds relationships and builds graphs based on the processed data. The question is, can we get the data values that AppleHealth generates for itself (the data that is displayed on a graph inside AppleHealth)?

    [Upd.22:28]
    Got it. If you need to receive data processed by the AppleHealth application, you must use the healthStore.ReadStatisticsCollection method
    In my case it`s look like this:

    private async UniTask<HealthStatisticsCollection> ReadHealthStatisticData(HKDataType dataType, DateTimeOffset startDate, DateTimeOffset endDate)
    {
    string typeName = HealthKitDataTypes.GetIdentifier(dataType);
    bool isGetData = false;

    Predicate predicate = new Predicate();
    TimeSpan timespan = new TimeSpan(1, 0, 0);
    HealthStatisticsCollection currentHealthStatistics = null;
    healthStore.ReadStatisticsCollection(dataType, predicate, StatisticsOptions.CumulativeSum, startDate, timespan, delegate (HealthStatisticsCollection healthStatistics, Error error)
    {
    currentHealthStatistics = healthStatistics;
    ShowError(error);
    isGetData = true;
    });

    await UniTask.WaitUntil(()=> isGetData, cancellationToken: _cts.Token);
    return currentHealthStatistics;
    }
     
    Last edited: Feb 2, 2024
  40. Aldar_Ochirov

    Aldar_Ochirov

    Joined:
    May 19, 2023
    Posts:
    2
    You need to use async (i use UniTask)

    Something like this:
    private async UniTask<List<QuantitySample>> ReadCumulativeQuantityDataToList(HKDataType dataType, DateTimeOffset startDate, DateTimeOffset endDate)
    {
    string typeName = HealthKitDataTypes.GetIdentifier(dataType);
    bool isGetSamples = false;
    var currentSamples = new List<QuantitySample>();
    healthStore.ReadQuantitySamples(dataType, startDate, endDate, delegate (List<QuantitySample> samples, Error error)
    {
    bool isWatch = samples.Exists(t => t.source.productType.Contains(APPLE_WATCH_SOURSE, StringComparison.InvariantCultureIgnoreCase));

    if (isWatch)
    {
    currentSamples = samples.Where(samples
    => samples.source.productType.Contains(APPLE_WATCH_SOURSE, StringComparison.InvariantCultureIgnoreCase)).ToList();
    }
    else
    {
    currentSamples = samples;
    }
    ShowError(error);
    isGetSamples = true;
    });
    await UniTask.WaitUntil(() => isGetSamples, cancellationToken: _cts.Token);
    return currentSamples;
    }
     
  41. leisztom

    leisztom

    Joined:
    Aug 21, 2018
    Posts:
    1
    Hi beliefengine, is there a way to add to the Mindful Minutes in Apple Health with your asset?
     
  42. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    38
    Yes, BEHealthKit supports reading & writing Mindful Sessions. In the HealthKitFullTest.cs example file, there's a short bit of sample code for writing one.
     
    dleight and leisztom like this.
  43. Cywizz

    Cywizz

    Joined:
    Oct 5, 2017
    Posts:
    17
    Hi beliefengine,

    I have used your sdk the last few months and it has helped us a lot with our fitness app.
    There is 1 thing our client requested, which I saw you briefly talked about a few years ago...background processing.

    Is there anything that perhaps changed with this? Currently, as part of the game loop, we pull data on a schedule and run it through a rules engine to determine certain rewards for the player. We only use Steps and Calories in our app.

    When the app is minimized, it seems nothing happens, until you focus the app again.
    We send out notifications to the player when certain goals where reached, but those obviously only triggers after the focus was given to the app.

    Is there any way that this can be done with all the recent changes, either on your side or apple's side that you are aware off? The reason I asked is that the client uses a lot of these fitness apps, and most of them does background data collection from apple health.
    Or is this something that can only be done with native code, outside of your sdk?
     
  44. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    38
    Background delivery is still rather limited, but it should be technically possible. There are 3 things you have to do:

    1. you must call EnableBackgroundDelivery(dataType, updateFrequency) first. (keep in mind most datatypes have an internal, undocumented minimum update frequency).
    2. In your Xcode project's entitlements file, you'll need to manually set com.apple.developer.healthkit.background-delivery to true.
    3. Launch your Observer Query (it only works for Observer Queries).

    And finally, the biggest restriction – as far as I'm aware, background delivery will not work if the device is locked with a passcode. Or at least, that was true the last time I checked – but because Apple takes privacy of people's health data very seriously, I highly doubt that has changed.

    It's possible other apps get around that by including WatchKit functionality. That, unfortunately, is not something I''ve been able to figure out how make a pure Unity wrapper for. And I don't want to add anything that requires dipping into native development.
     
    Cywizz likes this.
  45. Salazifel

    Salazifel

    Joined:
    Nov 23, 2022
    Posts:
    1
    Hello!

    Is there Android Health Kit integration planned as well? It would be great to be able to easily deploy apps to both platforms using Health Data.

    Best regards