Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Join us on Dec 8, 2022, between 7 am & 7 pm EST, in the DOTS Dev Blitz Day 2022 - Q&A forum, Discord, and Unity3D Subreddit to learn more about DOTS directly from the Unity Developers.
    Dismiss Notice
  3. Have a look at our Games Focus blog post series which will show what Unity is doing for all game developers – now, next year, and in the future.
    Dismiss Notice

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:
    36
    So I've been working on this, and it's been available for a while now, but I never made a forum thread for it. So with the 1.9 release, here it is!



    Read HealthKit data in your Unity iOS apps!

    Quickly & easily integrate the HealthKit Framework into your app and start reading health data. Just add a couple behaviors to an object in the scene & choose the data types you want to read in the inspector. Includes thorough documentation to get you started (and full class documentation online). There's an example scene, and full source code included so you can fully tailor it to your needs.

    Features:
    • Read & write quantities like # of steps, calories & other nutritional data, heart rate, blood pressure etc.
    • Read & write sleep data
    • Read & write workout data
    • and more!

    1.x supports all the core HealthKit functionality, but it's still not 100% complete. I'm actively adding more functionality as time goes on, and keeping it up-to-date with iOS updates. And if there's something missing, that you want to see supported, don't be afraid to ask!

    NOTE: HealthKit requires iOS 8+, and is only supported on iPhone 4s and later, or iPod touch 5th generation

    https://assetstore.unity.com/packages/tools/integration/behealthkit-39962

    -----------

    It's a niche little asset, but the only one of its kind! I keep it up-to-date with each release of iOS, and am steadily adding support for all the features HealthKit supports. I'm usually able to respond to support requests within a day.

    I don't really have any FAQs at the moment, but I rely heavily on feature requests from users to guide which features to prioritize adding, so if this thread sees any traction, I think it'll be a good place to track that.
     
    Last edited: Mar 20, 2020
    skillDev5235 likes this.
  2. TijsVdV

    TijsVdV

    Joined:
    Mar 7, 2017
    Posts:
    23
    Nice plugin. We are currently using it for an activity application. Recently updated the plugin to 1.9 but now it aint building anymore in xcode (Version 11.2.1). We are getting several errors. Do you have any idea what might be causing them?
     

    Attached Files:

  3. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    36
    I'm really sorry to hear that. While I can't say for sure what's causing it, I have a couple ideas.

    First, the last version did a little bit of restructuring, which I really should have called out in the release notes. I apologize for that. The first thing I'd try is deleting the BEHealthKit folder from your Unity project & reimporting.

    If that doesn't work, it might be a little trickier, but I'll see what I can do. What version of Unity are you using? In the past, I've had to build the package differently for different versions of Unity, so there might be something particular to yours that I missed.
     
  4. TijsVdV

    TijsVdV

    Joined:
    Mar 7, 2017
    Posts:
    23
    I deleted fully the old plugin then reimported the new one. This solved all the problems. Might have been that some old data was still lingering in the project. Thx for your help!
     
    beliefengine likes this.
  5. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    36
    Great! I'm glad to hear it.
     
  6. Shhteve

    Shhteve

    Joined:
    Jan 23, 2013
    Posts:
    8
    @beliefengine Does this plugin have any way of allowing you to track the health kit data while running in the background? For instance, if you wanted to send a push notification to the user upon them reaching xxxx steps?
     
  7. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    36
    It does have limited support for HKObserverQueries, which is what you would use for something like this. But local notifications are mostly outside the purview of the asset, so that's something that, at least with the current version of BEHealthKit, you'd be on your own for. (Push notifications, that is, notifications sent from an outside server, are definitely outside the scope of this asset)

    More importantly, though, I don't think your specific for-instance is possible at all. I would need to do some more research, but it appears there are 2 main problems:
    1. the update frequency for certain data types is locked to a minimum, step count specifically appears to be hourly. That is, you will only get step notifications once an hour.
    2. To protect the user's privacy, the health store is encrypted while the device is locked. Which means it can be written to, but not read – so I don't think there'd be a way to tell if the threshold of xxxx steps has been met. Additionally, while I'd need to test this myself, I don't think the observer gets called at all unless the device is unlocked.
    If those limitations are things you think you can live with, I'd be more than happy to help & investigate further. But otherwise, I hate to be the bearer of bad news, but there's really no way around them.
     
  8. jalemanyf

    jalemanyf

    Joined:
    Jun 16, 2013
    Posts:
    25
    Hi @beliefengine,

    I have a question about how I can use your plugin:

    Could I start / stop a hearthRate and syncronize it ? I need to make some measures with the Watch and the phone at the same time and I need read the values at the same time.

    I can recollect the data with some little delay ( that's not important to wait a little for me ) but, the start / stop must be exact.

    Thanks in advance,

    Josep Alemany
     
  9. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    36
    Unfortunately, no. While you do have precise control over the exact times for which you query for heart rate samples, the HealthKit API, and thus BEHealthKit, do not offer include support for taking the samples directly. For that you'd need something to talk directly to a bluetooth peripheral (or whatever device you're planning on using). BEHealthKit could then let you write that sample to the phone's Health store, but that's it.
     
  10. EgoJacky

    EgoJacky

    Joined:
    Aug 15, 2017
    Posts:
    24
    Hi @beliefengine,

    I have a Problem to use this Plugin in combination with Assembly Definitions. Sadly there is no description inside the documentation on how to use it with Assembly Definitions.

    My Assembly Definition Setup:
    I created a Assembly Defintion inside the Main-Folder (Assets/BEHealthKit/) that includes all platforms. And a Assembly Definitions inside the Editor-Folder (Assets/BEHealthKit/Editor) that includes only Editor. The Assembly Defintions inside the Main-Folder has a Reference to the Editor Assembly Definition.

    But there is a error that I can not solve, seems like a Serialization problem
    SerializationException: Unable to find assembly 'Assembly-CSharp'.

    upload_2020-7-23_18-21-54.png

    Is there anything I did wrong with my Assembly Definitions setup? Or is this a different Problem?

    I am using Unity 2018.4.22f1 on Windows (64Bit)

    Best Wishes
    EgoJacky
     
  11. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    36
    What problem are you trying to solve with the assembly definitions?

    While I don't officially support BEHealthKit on Windows, I'll do my best to try & solve this issue. I'll poke around a little bit, but knowing what you're trying to achieve may help.

    EDIT this may just be a start, but try removing the HealthKitDataTypes component in your scene & then re-adding it. Looks like it being serialized before adding the assembly definition might be what's triggering this particular error.
     
    Last edited: Jul 29, 2020
  12. EgoJacky

    EgoJacky

    Joined:
    Aug 15, 2017
    Posts:
    24
    oh thanks, that actually fix this Issue. Nice.
    We are using Assembly Definitions in our project to reduce the compiling time, we have to add new assembly definitions for every Plugin that we buy from the Asset-Store, otherwise we cannot export our game. Sometimes it makes some trouble.

    But thanks for your response, the error is gone.

    EgoJacky
     
    beliefengine likes this.
  13. And1Mixtape11

    And1Mixtape11

    Joined:
    May 15, 2015
    Posts:
    9
    Hello guys!

    Thanks for your work. Your plugin is awesome.

    I'm currently working on a project in which we use your plugin, everything is working great, but we have a problem.

    We can't get real active time.
    For example, if I have 20k steps, the active time that we calculate using your plugin may show only 20 active minutes or less, which is not real. It should be rather 2-3 hours.

    Is there any other way to get accurate active time for walking and cycling?

    Thank you a lot for your help!
     

    Attached Files:

  14. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    36
    Hmm, that's a tough one. As you've noticed, the step samples are all in discrete chunks. And the start/end time is for the sample, not the activity itself. There really isn't a "time walking" data type in HealthKit; the closest would be one of the workout types, but that'd require the user to manually start & stop a walking (or cycling, I suppose) workout.

    **BUT** I think you want to use TotalSeconds there instead of Seconds. The latter merely gives you the seconds component of the timespan, rather than the total time. Try changing that, and see if the #s are closer to what you're expecting.
     
    And1Mixtape11 likes this.
  15. And1Mixtape11

    And1Mixtape11

    Joined:
    May 15, 2015
    Posts:
    9
    Hi guys!

    I have a problem with publishing an application to the store due to Clinical Health Records API.
    I don't use it but it looks like the plugin contains this inside.

    I am using the most recent 1.10 version of the plugin.
    I attached a screenshot.

    How can this be solved?

    Thanks!
     

    Attached Files:

  16. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    36
    I recommend fully deleting BEHealthKit from your project & then reimporting it. Unfortunately, the last update (that quarantined the Clinical Health Records API) required a fair amount of shuffling things around, and it looks like some of the old code got left over.

    After the clean install, just delete (or don't include in the first place!) the Clinical Record Support.unitypackage. There should be *absolutely no* trace left. I added the (hopefully) because, unfortunately, I don't really have any way to test... other than make an app and put it through the review process myself.

    I do now know that Apple uses a string-based method to locate usage of the API, so it's not enough to just not call it – that's why the last release of BEHEalthKit triggered it. It was picking up on some of the C# helper classes, even though they weren't actually able to call the native API. If you know what string Apple is looking for, you can use grep to do a spot check on the built app. For example, right click "show in Finder" on the product in the Xcode project, and then go to that folder in a Terminal window:

    Code (csharp):
    1. grep -r "ClinicalRecord" .
    That should return no results – if it does, something went wrong.
     
  17. And1Mixtape11

    And1Mixtape11

    Joined:
    May 15, 2015
    Posts:
    9
    That works, thank you!
     
    beliefengine likes this.
  18. And1Mixtape11

    And1Mixtape11

    Joined:
    May 15, 2015
    Posts:
    9
    Hey guys!

    Is it possible with a plugin to start a process that will count steps in the background for a closed or minimized app? We need this to send a local push notification when the user reaches the daily rate of steps. Is it possible to implement this somehow by means of a plugin?
     
  19. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    36
    Unfortunately, probably not. Background processes are limited to very specific categories, and while there *is* a mechanism for an "observer query" in HealthKit that run at certain intervals (steps I think are hourly), it has the extra limitation of not running if the device is locked.

    That last limitation is probably the dealbreaker, but assuming you worked within those limitations, you'd need your own mechanism for checking if the step goal had been met & sending the local notification. To be honest, I'm not sure if you'd even be able to do that in C# or if you'd need to drop down into native code.
     
  20. marchent

    marchent

    Joined:
    Jan 28, 2015
    Posts:
    5
    Great asset.
    Please support Android Google Fit.
    Best regards.
     
  21. TijsVdV

    TijsVdV

    Joined:
    Mar 7, 2017
    Posts:
    23
    Hi, did something change to the ReadStatistics function? The callbacks are no longer getting fired. This an issue with iOS 14 or are we doing something wrong? This actually worked like a charm before.

    Edit1: I just noticed we are getting this error.
    error from HealthKit plugin: ERROR domain:com.apple.healthkit code:11 "No data available for the specified predicate."

    Edit2: The read steps function for example still works.
     
    Last edited: Oct 8, 2020
  22. anu_dev

    anu_dev

    Joined:
    Feb 8, 2018
    Posts:
    2
    Hi ,I am looking for some help to fix the error that I am getting when I use BEHEALTHKIT plugin.
    I have added all the files that mentioned in the documentation and ended up with a building error
    ❌ error: Provisioning profile "match AdHoc ......" doesn't support the HealthKit capability. (in target 'Unity-iPhone' from project 'Unity-iPhone')
    I have added HealthKit capability from developer.apple.com for this provisioning profile .but while building I found that HealthKitBuildProcessor.cs file is not adding healthKit capability through ProjectCapabilityManager class.
    HealthKit implementation is a critical requirement for my project and I am blocked with this error.
    Any help would be greatly appreciated !
     
  23. And1Mixtape11

    And1Mixtape11

    Joined:
    May 15, 2015
    Posts:
    9
    Hey guys!

    Started getting this error when migrated the project from Unity 2019.2.21 to Unity 2020.1.16. It worked just fine before.
    Can you pls help me with this issue?

    P.S. Attached the error body and the code snippet below.

    FormatException: Input string was not in a correct format.
    System.Number.ParseDouble (System.String value, System.Globalization.NumberStyles options, System.Globalization.NumberFormatInfo numfmt) (at <00000000000000000000000000000000>:0)
    BeliefEngine.HealthKit.Quantity..ctor (System.Xml.XmlNode node) (at <00000000000000000000000000000000>:0)
    BeliefEngine.HealthKit.QuantitySample..ctor (System.Xml.XmlNode node) (at <00000000000000000000000000000000>:0)
    BeliefEngine.HealthKit.HealthData.ParseQuantitySamples () (at <00000000000000000000000000000000>:0)
    BeliefEngine.HealthKit.HealthStore.ParseHealthXML (System.String xmlString) (at <00000000000000000000000000000000>:0)
     

    Attached Files:

    • 1.png
      1.png
      File size:
      28 KB
      Views:
      238
  24. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    36
    I really don't know what changed in Unity 2020 that could cause this. Try this to get a better idea of what's happening. In HealthData.cs, change
    Code (CSharp):
    1. samples.Add(new QuantitySample(node));
    to
    Code (CSharp):
    1.  
    2. try {
    3.     samples.Add(new QuantitySample(node));
    4. }
    5. catch (Exception e) {
    6.     Debug.LogError($"error parsing Quantity Sample. Node: {node.OuterXml}");
    7. }
    8.  
    and share the log with me, either here or privately.
     
  25. And1Mixtape11

    And1Mixtape11

    Joined:
    May 15, 2015
    Posts:
    9
    Hey man!
    Thank you, did it!
    Here is the new log

    error parsing Quantity Sample. Node: <quantitySample><source><bundleID>com.apple.health.BEDB68F8-4F5C-49F6-8A47-45E53C726E5D</bundleID><productType>iPhone10,3</productType><source>iPhone</source><version>14.1</version></source><quantity><value>0.003678517458043932</value><unit>mi</unit></quantity><sampleType><aggregationStyle>discreteEquivalentContinuousLevel</aggregationStyle><identifier>HKQuantityTypeIdentifierDistanceWalkingRunning</identifier></sampleType><sumQuantity>0.003678517458043932</sumQuantity><endDate>1606941801.852435</endDate><startDate>1606941799.286411</startDate><quantityType><aggregationStyle>discreteEquivalentContinuousLevel</aggregationStyle><identifier>HKQuantityTypeIdentifierDistanceWalkingRunning</identifier></quantityType></quantitySample>
    BeliefEngine.HealthKit.HealthDataParseQuantitySamples()
    BeliefEngine.HealthKit.HealthStoreParseHealthXML(String)
     
  26. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    36
    That... all looks fine. And it parses correctly on my setup :(
    Everything should be localized correctly by default, but... What's the language & region set to on your device? Based on the error & the XML you supplied, it's looking to me like it's expecting the doubles to use a comma to separate the decimal place but getting a period. Or something along those lines.
     
  27. And1Mixtape11

    And1Mixtape11

    Joined:
    May 15, 2015
    Posts:
    9
    Yeah, you're right. I am in Ukraine and my region was appropriate. Russian language. I switched it to English in the settings on my iPhone and now I have no such error, but it would still be good to handle it somehow in the plugin.

    Thanks for the help!
     
  28. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    36
    Got it. Yeah, I did some digging and it looks like there's a part of the XML framework on the native side that isn't localizing the numbers that it sends over. Doesn't matter for things like step count, since they're integers & are the same regardless, but for distances that aren't in whole numbers, it can trigger this error.

    Good news is, I've already got a fix that I'm in the process of testing. I'll be sure to test this with Ukraine / Russian tomorrow, to make extra sure, but it should be ready to go pretty soon. I absolutely don't want you to have to switch your locale/language in order to use BEHealthKit, so this fix is a high priority.
     
  29. And1Mixtape11

    And1Mixtape11

    Joined:
    May 15, 2015
    Posts:
    9
    Hey guys!

    Is it possible to open any of these pages in these screenshots using the plugin after it already used once? For example, when I first launched the app using the plugin, I saw a screen on which I'm able to allow to read some data. Is it possible to add settings in my app and so that from it I can reopen the screen that allows you to set read permissions?
     

    Attached Files:

    • 1.jpg
      1.jpg
      File size:
      39.7 KB
      Views:
      245
    • 2.jpg
      2.jpg
      File size:
      16.7 KB
      Views:
      245
  30. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    36
    Short answer is, yes.
    Long answer is no – it's a little weird; the controls for it are lacking. Apple is understandably cagey about it in order to protect the user's privacy. So there's no way to trigger the dialogue manually.

    The way it works in practice is, as long as you're requesting authorization before attempting to do any read/writes of health data, the system will display the appropriate dialogue. The first time. If the system has already asked for permission for the types, it won't ask again – the only way to change it is for the user to manually do it in settings, or to reinstall the app. But if you ask for different types, it will re-trigger the dialogue.
     
  31. power6574

    power6574

    Joined:
    Apr 29, 2020
    Posts:
    6
    Hi, Thank you for your Asset.

    I have the latest version BeHealthKit. This asset is awesome! I love it.

    Recently, I have a few questions. I try solving a few problems. I failed. hah-

    There are only two questions.

    First, in mobilities, I found my stepLength is 0.001and walkingSpeed is 76.

    Maybe I think that In this code StepLength is WalkingSpeed in Iphone Healthkit.

    I guess that 0.001 is 1 m/s.

    As a result, the value of StepLength is changed to the value of WalkingSpeed.

    Second, How to use the value of HeartRate or the other kind of HeartRate?

    In my case,

    In <HealthStore.cs>

    1. public void ReadHeartRate(HKDataType dataType, DateTimeOffset startDate, DateTimeOffset endDate, ReceivedHealthData<List<QuantitySample>, Error> handler)
    {
    this.receivedQuantitySamplesHandlers[dataType] = handler;
    this.ReadQuantity(dataType, startDate, endDate, false);
    }

    2. public void ReadHeartRateAverage(HKDataType dataType, DateTimeOffset startDate, DateTimeOffset endDate, ReceivedHealthData<List<QuantitySample>, Error> handler)
    {
    this.receivedQuantitySamplesHandlers[dataType] = handler;
    this.ReadQuantity(dataType, startDate, endDate, false);
    }

    And <HelthkitTest.cs>

    1. if (dataType == HKDataType.HKQuantityTypeIdentifierHeartRate)
    {
    double maxHeartRate = 0;
    healthStore.ReadHeartRate(HKDataType.HKQuantityTypeIdentifierHeartRate , start, now, delegate (List<QuantitySample> samples, Error error) {
    foreach(var sample in samples)
    {
    maxHeartRate = sample.averageQuantity;
    }
    if (maxHeartRate > -1)
    {
    resultsLabel.text = "heartRate : " + maxHeartRate;
    }
    else
    {
    resultsLabel.text = "Error : The data is empty";
    }
    reading = false;
    });
    }

    2. if (dataType == HKDataType.HKQuantityTypeIdentifierWalkingHeartRateAverage)
    {
    double averageHeartRate = 0;
    healthStore.ReadHeartRateAverage(HKDataType.HKQuantityTypeIdentifierWalkingHeartRateAverage, start, now, delegate (List<QuantitySample> samples, Error error) {
    foreach (var sample in samples)
    {
    averageHeartRate = sample.averageQuantity;
    }
    if (averageHeartRate > -1)
    {
    resultsLabel.text = "heartRate : " + averageHeartRate ;
    }
    else
    {
    resultsLabel.text = "The data is empty.";
    }
    reading = false;
    });
    }

    I try building the test game.
    When I select HeartRate, the value of heartrate is only the latest value one. ( I checked your commentary in .cs, but In your debug.log also the value is nothing. it printed "0" )

    When I select HeartRateAverage in dropdown UI, application is crashed.

    I want to receive max value of heartRate. In iPhone Healthkit, it is shown that "min ~ max / bpm". I need max /bpm.

    I want to receive average value of WalkingRunningHeartRateAverage or RestingHeartRate.


    Thank you for reading my questions.

    I need your help.
     
  32. greay

    greay

    Joined:
    Mar 23, 2011
    Posts:
    85
    I'm not entirely sure what your question here is, but there's no need to guess – every QuantitySample includes a unit property. It can be different depending on your locale, but walking speed is a distance, so it'll either be in miles or meters. Walking speed is distance/time, so that'll be either m/s or mi/s.

    This seems unnecessary – since you're still passing in the data type, you could use
    ReadQuantitySamples
    just as well.

    Each sample also has a minimumQuantity and a maximumQuantity. This isn't going to be set for every data type, but it will for heart rate. They'll be set to the minimum & maximum of the sample duration – if you want the maximum over a larger time, just take the largest value you get back. So instead of:

    Code (csharp):
    1.  
    2. foreach(var sample in samples) {
    3.     maxHeartRate = sample.averageQuantity;
    4. }
    5. if (maxHeartRate > -1) {
    6.     resultsLabel.text = "heartRate : " + maxHeartRate;
    7. } else {
    8.     resultsLabel.text = "Error : The data is empty";
    9. }
    10.  
    do something like this:

    Code (csharp):
    1.  
    2. foreach(var sample in samples) {
    3.     if (sample.maximumQuantity > maxHeartRate) {
    4.         maxHeartRate = sample.maximumQuantity;
    5.     }
    6. }
    7.  
    I'm really not sure about the crash – I'll need more info regarding that. Hopefully this helps you a little, though!
     
  33. Sashimiii

    Sashimiii

    Joined:
    Sep 26, 2017
    Posts:
    15
    Hii, I have a question. Currently I have an error: "unable to read NSHealthShareUsageDescription":

    unable to read NSHealthShareUsageDescription
    UnityEngine.Debug:LogError(Object)
    HealthKitBuildProcessor:ProcessInfoPList(String, Boolean) (at Assets/BEHealthKit/Editor/HealthKitBuildProcessor.cs:124)
    HealthKitBuildProcessor:OnPostprocessBuild(BuildTarget, String) (at Assets/BEHealthKit/Editor/HealthKitBuildProcessor.cs:81)
    UnityEditor.BuildPlayerWindow:BuildPlayerAndRun() (at /Users/builduser/buildslave/unity/build/Editor/Mono/BuildPlayerWindow.cs:136)


    Could you help me with this?
     
  34. unity_tb

    unity_tb

    Joined:
    Oct 25, 2017
    Posts:
    2
    Hi, I am having an issue with using ReadStatistics.
    I want to exclude certain sources but using StatisticsOptions.SeparateBySource is useless, because the statistics HealthStatistics class does not include a source information although HKStatistics contains a Property var sources: [HKSource].
    Alternatively, i would like to use Predicates for the filtering, but it is onyl supported for Statistics Collections at the moment

    Thanks for you help.
     
    Last edited: Feb 4, 2021
  35. gegagome

    gegagome

    Joined:
    Oct 11, 2012
    Posts:
    384
    Hi there

    Can you pull live heart rate from Apple Watch?

    For instance can you see current heart rate in your Unity project?

    Thanks
     
  36. Rave-TZ

    Rave-TZ

    Joined:
    Jul 21, 2013
    Posts:
    57
    Is it possible to retrieve near real-time heart rate data with this plugin?
     
  37. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    36
    I'm really sorry for the late reply!

    Unfortunately, no. The only data type that you're able to get near-realtime data for is step count, through the pedometer (which isn't technically part of HealthKit, but I do include in this asset).

    For everything else, it's a bit complicated. While it is possible to set up an observer to be notified of data as it comes in, it isn't realtime. The precise rate is undocumented and may differ depending on the version of iOS, watchOS, and the generation of the watch itself. It's also possible to get more frequent updates if a workout is running on the watch, but I don't have any support for watch connectivity, yet. (I'm investigating it, but it's still quite a ways off)
     
  38. Gentlemanni

    Gentlemanni

    Joined:
    Jan 27, 2018
    Posts:
    3
    Hello,

    Thank you for your work with the plugin! It seems to be a very good plugin, but I could use some help with it please.

    I'm currently working on a project in which we are using your plugin, but I have problems getting step counting to work.

    Here is a picture of code I'm using:
    upload_2021-4-28_8-52-35.png

    Here is picture of debug texts that code above gives:
    upload_2021-4-28_8-53-4.png

    On Awake() method I call Authorize with data types:

    Code (CSharp):
    1. _healthStore = GetComponent<HealthStore>();
    2. _dataTypes = GetComponent<HealthKitDataTypes>();
    3. _healthStore.Authorize(_dataTypes);
    4. _debugText.text += _healthStore + " Authorized ";

    In Xcode I've added NSHealthShareUsageDescription and NSHealthUpdateUsageDescription. I've even tried to add NSMotionUsageDescription although I'm not using Pedometer itself.

    Like debug text shows: ReadQuantitySamples delegate doesn't get any replies. HealthStore.ReadSteps neither gets any replies.

    I've tried to follow your documentation, but I'm not sure if it's up to date.
    This code from the documentation gives errors,

    Code (CSharp):
    1. DateTimeOffset now = DateTimeOffset.UtcNow;
    2. DateTimeOffset start = now.AddDays(-1);
    3. this.healthStore.ReadQuantitySamples(HKDataType.HKQuantityTypeIdentifierStepCount, start, now, delegate(List<QuantitySample> samples) {
    4.    foreach (QuantitySample sample in samples) {
    5.        Debug.Log(String.Format(- {0} from {1} to {2}”, sample.quantity.doubleValue, sample.startDate, sample.endDate);
    6.    }
    7. });
    as you can see here:
    upload_2021-4-28_8-54-36.png

    So I fixed it to look like this,

    Code (CSharp):
    1. DateTimeOffset end = DateTimeOffset.UtcNow;
    2. DateTimeOffset start = end.AddDays(-days);
    3. _healthStore.ReadQuantitySamples(HKDataType.HKQuantityTypeIdentifierStepCount, start, end, delegate (List<QuantitySample> samples, BeliefEngine.HealthKit.Error error) {
    4.     foreach (QuantitySample sample in samples) {
    5.         _debugText.text += "Value: " + sample.quantity.doubleValue + " from " + sample.startDate + " to " + sample.endDate;
    6.     }
    7. });
    as you saw in the very first picture.

    Any ideas what is causing my problem, and how to fix it? I hope you have time to answer me as soon as possible. I've been fighting with this problem for way too long. Let me know if you need any more information to solve this problem, please.


    Best Regards
    Gentlemmani
     
  39. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    36
    Hi, I don't know if it was you or another team member that I replied to via email, but it must've got lost in spam or something. In any case, here's what I put in the email:

    Your code looks good, to be honest, and when I plugged it in to my test scene, it ran fine & I got steps back. I wouldn't use both use *both* ReadSteps and ReadQuantitySamples, but for the purpose of troubleshooting it's fine.

    Would you mind sending the logs from the Xcode console? It is very weird that you're not getting *either* callback, so it does seem like it's failing somewhere in the native code & I'm hoping that will shed some light on where.

    (and thanks for pointing out the problems with the documentation – I do need to do a pass & update the code samples to include the error callback)
     
  40. Gentlemanni

    Gentlemanni

    Joined:
    Jan 27, 2018
    Posts:
    3
    Hi. Yeah, it was me. I think the email got lost somewhere, because I never got answer,but that's not important. Maybe it's better to share this problem here anyway if someone else have similar problem.

    We have had a lot of problems with our hardwares and systems lately, why it took a while to get those logs out but here:

    root name: quantity\
    BeliefEngine.HealthKit.HealthData:.ctor(String)\
    BeliefEngine.HealthKit.HealthStoreParseHealthXML(String)\
    \
    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)\
    \
    ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.\
    Parameter name: index\
    at System.ThrowHelper.ThrowArgumentOutOfRangeException (System.ExceptionArgument argument, System.ExceptionResource resource) [0x00000] in <00000000000000000000000000000000>:0 \
    at System.ThrowHelper.ThrowArgumentOutOfRangeException () [0x00000] in <00000000000000000000000000000000>:0 \
    at StepManager.HandleNewStepData (StepList stepList) [0x00000] in <00000000000000000000000000000000>:0 \
    at System.Action`1[T].Invoke (T obj) [0x00000] in <00000000000000000000000000000000>:0 \
    at StepCounter.DataReceived (System.Collections.Generic.List`1[T] samples, BeliefEngine.HealthKit.Error error) [0x00000] in <00000000000000000000000000000000>:0 \
    at BeliefEngine.HealthKit.ReceivedHealthData`2[T,Error].Invoke (T result, Error error) [0x00000] in <00000000000000000000000000000000>:0 \
    \
    (Filename: currently not available on il2cpp Line: -1)\
    \
    root name: combined\
    BeliefEngine.HealthKit.HealthData:.ctor(String)\
    BeliefEngine.HealthKit.HealthStoreParseHealthXML(String)\
    \
    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)\​

    And here some more:

    reading quantity from:\
    -5/2/2021 11:57:40 AM +00:00 (1619956660.10629)\
    to:\
    -5/3/2021 11:57:40 AM +00:00 (1620043060.10629)\
    BeliefEngine.HealthKit.HealthStore:ReadQuantity(HKDataType, DateTimeOffset, DateTimeOffset, Boolean)\
    StepCounter:GetiOSSteps(Int32)\
    <IOSStepCoroutine>d__13:MoveNext()\
    UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)\
    \
    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)\
    \
    2021-05-03 14:57:40.107744+0300 liikkuujklpilottitest[14860:10554388] [reading quantity from Sun May 2 14:57:40 2021 to Mon May 3 14:57:40 2021]\
    reading quantity from:\
    -5/2/2021 11:57:40 AM +00:00 (1619956660.10629)\
    to:\
    -5/3/2021 11:57:40 AM +00:00 (1620043060.10629)\
    BeliefEngine.HealthKit.HealthStore:ReadQuantity(HKDataType, DateTimeOffset, DateTimeOffset, Boolean)\
    StepCounter:GetiOSSteps(Int32)\
    <IOSStepCoroutine>d__13:MoveNext()\
    UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)\
    \
    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)\
    \
    2021-05-03 14:57:40.109634+0300 liikkuujklpilottitest[14860:10554388] [reading quantity from Sun May 2 14:57:40 2021 to Mon May 3 14:57:40 2021]\
    2021-05-03 14:57:40.145412+0300 liikkuujklpilottitest[14860:10554815] --- querying HealthKit took 0.037407 seconds ---\
    2021-05-03 14:57:40.154125+0300 liikkuujklpilottitest[14860:10554815] --- querying HealthKit took 0.044313 seconds ---\
    root name: quantity\
    BeliefEngine.HealthKit.HealthData:.ctor(String)\
    BeliefEngine.HealthKit.HealthStoreParseHealthXML(String)\
    \
    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)\
    \
    error parsing Quantity Sample. Node: <quantitySample><source><bundleID>com.apple.health.BA86254E-FE2D-4EF5-A231-ECDB51B408EC</bundleID><productType>iPhone10,4</productType><source>iPhone (Ville)</source><version>14.4.2</version></source><quantity><value>1\'a0464</value><unit>count</unit></quantity><sampleType><aggregationStyle>discreteEquivalentContinuousLevel</aggregationStyle><identifier>HKQuantityTypeIdentifierStepCount</identifier></sampleType><sumQuantity>1\'a0464</sumQuantity><endDate>1619969671.72</endDate><startDate>1619969071.56</startDate><quantityType><aggregationStyle>discreteEquivalentContinuousLevel</aggregationStyle><identifier>HKQuantityTypeIdentifierStepCount</identifier></quantityType></quantitySample>\
    BeliefEngine.HealthKit.HealthDataParseQuantitySamples()\
    BeliefEngine.HealthKit.HealthStoreParseHealthXML(String)\
    \
    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)\
    \
    FormatException: Input string was not in a correct format.\
    at System.Number.ParseDouble (System.String value, System.Globalization.NumberStyles options, System.Globalization.NumberFormatInfo numfmt) [0x00000] in <00000000000000000000000000000000>:0 \
    at BeliefEngine.HealthKit.Quantity..ctor (System.Xml.XmlNode node) [0x00000] in <00000000000000000000000000000000>:0 \
    at BeliefEngine.HealthKit.QuantitySample..ctor (System.Xml.XmlNode node) [0x00000] in <00000000000000000000000000000000>:0 \
    at BeliefEngine.HealthKit.HealthData.ParseQuantitySamples () [0x00000] in <00000000000000000000000000000000>:0 \
    at BeliefEngine.HealthKit.HealthStore.ParseHealthXML (System.String xmlString) [0x00000] in <00000000000000000000000000000000>:0 \
    \
    (Filename: currently not available on il2cpp Line: -1)\
    \
    root name: combined\
    BeliefEngine.HealthKit.HealthData:.ctor(String)\
    BeliefEngine.HealthKit.HealthStoreParseHealthXML(String)\
    \
    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)\
    \
    FormatException: Input string was not in a correct format.\
    at System.Number.ParseDouble (System.String value, System.Globalization.NumberStyles options, System.Globalization.NumberFormatInfo numfmt) [0x00000] in <00000000000000000000000000000000>:0 \
    at BeliefEngine.HealthKit.HealthStore.ParseHealthXML (System.String xmlString) [0x00000] in <00000000000000000000000000000000>:0 \
    \
    (Filename: currently not available on il2cpp Line: -1)\
    \
    reading quantity from:\
    It seems like there is some kind of error when parsing Quatity Sample and some FormatExceptions.

    This time I got response once at the start but step count was 0 and error message was: Authentication not determined.
    This was weird, but could it be that authentication is not working after all?

    [initializing]
    BeliefEngine.HealthKit.HealthKitDataTypes:Initialize()
    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)

    --- authorizing ---
    BeliefEngine.HealthKit.HealthStore:Authorize(HealthKitDataTypes, AuthorizationHandler)
    StepCounter:Awake()
    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)

    2021-05-03 14:57:25.526482+0300 liikkuujklpilottitest[14860:10554388] adding HKQuantityTypeIdentifierStepCount
    2021-05-03 14:57:25.527784+0300 liikkuujklpilottitest[14860:10554388] adding HKQuantityTypeIdentifierStepCount
    iOS 14.4.2 => API version: 0
    Mapbox.Unity.Location.LocationProviderFactory:InjectDeviceLocationProvider()
    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)


    Regards,
    Gentlemanni
     
  41. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    36
    "Authentication not determined" is (somewhat) normal, and something you should handle in your app. By design, for privacy reasons, it's impossible for you to know if the user has not authorized the data collection, or actively rejected it. Without more details, I can't really say why you got that in this particular case.

    Regarding the logs... yes, it is throwing an exception in ParseQuantitySamples() and it seems like there's some sort of invalid character, but it looks like there was some sort of formatting issue in what you posted (all of those stray '\' characters).

    There's a couple things that'd help me troubleshoot this:

    - first, what are the Language and Region of your test device?
    - if possible, could you attach the Xcode logs as a text file or email to us?
    - *EVEN BETTER*, if you could send us a sample project, that'd help immensely. I wasn't able to reproduce the issue with the code snippet above, but it's possible something else is interfering or something has changed in the interim.
     
  42. Gentlemanni

    Gentlemanni

    Joined:
    Jan 27, 2018
    Posts:
    3
    Hello,

    Alright, you got it. I tested to change the region to US and now it's working. My own region is Finland. In addition, I had to add a null check to List<QuantitySaples> response.

    I think there was same problem with the guy from Ukraine. Have you fixed it yet? Could you add Finland on the list as well? I'd appreciate a lot :)


    Best Regards,
    Gentlemanni
     
  43. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    36
    Region handling has been a sore spot in the past, just because of slight differences in how C# and Objective-C handles them, and passing dates and numbers between the two. And there are so many to test. It should, in theory, support any of them – but there's just so many variables at play, and unfortunately it's not something I can really write unit tests to catch, though I've started to do my best.

    Good news is, though, Finland does in fact use a number format that I hadn't come across yet, and I was able to reproduce the issue by setting my device's region. I should have a hotfix ready to submit to Unity by the end of the day.
     
  44. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    36
    it's been submitted for approval; let me know if it solves your issue.
     
  45. smallUser

    smallUser

    Joined:
    Sep 18, 2013
    Posts:
    9
    Hello,
    Thank you for creating this asset.
    Me and many other people has potential to buy this asset if you could add ability to run in the background.

    Maybe this API could help you to find the solution.
    API:
    canRunInBackground

    If true, the device is capable of delivering input while the application is running in the background, i.e. while Application.isFocused is false.

    https://docs.unity3d.com/Packages/c...ne_InputSystem_InputDevice_canRunInBackground


    runInBackground

    If enabled, input will be collected and processed while the application is running in the background (i.e. when = the application does not have focus).

    https://docs.unity3d.com/Packages/c...erimental_Input_InputSettings_runInBackground


    Calling iOS methods from Unity and vice versa
    https://medium.com/@rolir00li/integrating-native-ios-code-into-unity-e844a6131c21
     
  46. prototype7

    prototype7

    Joined:
    Aug 29, 2012
    Posts:
    12
    Hello,

    I want to ask
    In the iOS Native Healthkit, you can get the number of steps taken in the past 7 days by specifying the period.
    My question is does this asset able to get the data like in the iOS Native?
    Thanks in advance.

    Best Regards
     
  47. jackie217330

    jackie217330

    Joined:
    Sep 16, 2014
    Posts:
    1
    Hello,

    I have an issue with getting the step count every 30 seconds, and the samples returned from ReadQuantitySamples do not update. The samples update only after switching to the health detail in iphone setting, then switch back to my app.

    What I need is to obtain the last 30~60 seconds data, is there any suggestion?
     
  48. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    36
    I'm terribly sorry for the late replies; I've been swamped with other stuff lately.
     
  49. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    36
    Background support is something I've looked into in the past, but it's always been really tricky. iOS support for background processes is incredibly limited – it's something I keep coming back to, but the capabilities historically have been limited to certain restrictive categories, none of which really apply to what BEHealthKit is for.

    On top of that, whether a Unity app would even work in the background has always been an open question. This is the first I've actually seen regarding explicit support for it (though it seems specific to the Input System, and I don't see anything about iOS...) So I'll renew my investigation, and see if there's anything I can do.
     
  50. beliefengine

    beliefengine

    Joined:
    Nov 4, 2017
    Posts:
    36
    again, sorry for the late reply.

    Yes. BEHealthKit absolutely will allow you to do that.