HealthKit in Xamarin.iOS

Health Kit bietet einen sicheren Datenspeicher für die gesundheitsbezogenen Informationen von Benutzer*innen. Health Kit-Apps können mit der expliziten Berechtigung von Benutzer*innen in diesem Datenspeicher lesen und schreiben und Benachrichtigungen empfangen, wenn relevante Daten hinzugefügt werden. Apps können die Daten anzeigen, oder Benutzer*innen können die von Apple bereitgestellte Health-App verwenden, um ein Dashboard mit all ihren Daten anzuzeigen.

Da gesundheitsbezogene Daten so sensibel und entscheidend sind, ist Health Kit stark typiert, mit Maßeinheiten und einer expliziten Zuordnung mit dem Typ der aufgezeichneten Informationen (z. B. Blutdruck oder Herzfrequenz). Darüber hinaus müssen Health Kit-Apps explizite Berechtigungen verwenden, den Zugriff auf die jeweiligen Informationstypen anfordern, und der Benutzer muss der App explizit Zugriff auf diese Datentypen gewähren.

In diesem Artikel wird Folgendes eingeführt:

  • Sicherheitsanforderungen des Health Kit, einschließlich Anwendungsbereitstellung und Anfordern von Benutzerberechtigungen für den Zugriff auf die Health Kit-Datenbank;
  • Das Typsystem des Health Kit, das die Möglichkeit minimiert, Daten falsch anzuwenden oder zu interpretieren;
  • Schreiben in den freigegebenen, systemweiten Health Kit-Datenspeicher.

In diesem Artikel werden keine erweiterten Themen behandelt, z. B. Abfragen der Datenbank, Konvertieren zwischen Maßeinheiten oder Empfangen von Benachrichtigungen über neue Daten.

In diesem Artikel erstellen wir eine Beispielanwendung zum Aufzeichnen der Herzfrequenz des Benutzers:

A sample application to record the users heart rate

Anforderungen

Die folgenden Schritte sind erforderlich, um die in diesem Artikel beschriebenen Schritte auszuführen:

  • Xcode 7 und iOS 8 (oder höher) – Die neuesten Xcode- und iOS-APIs von Apple müssen auf dem Computer des Entwicklers installiert und konfiguriert werden.
  • Visual Studio für Mac oder Visual Studio – Die neueste Version von Visual Studio für Mac sollte auf dem Computer des Entwicklers installiert und konfiguriert werden.
  • iOS 8 (oder höher) Gerät – Ein iOS-Gerät, auf dem die neueste Version von iOS 8 oder höher zum Testen ausgeführt wird.

Wichtig

Health Kit wurde in iOS 8 eingeführt. Das Health Kit ist derzeit nicht im iOS-Simulator verfügbar, und für das Debuggen ist eine Verbindung mit einem physischen iOS-Gerät erforderlich.

Erstellen und Bereitstellen einer Health Kit-App

Bevor eine Xamarin iOS 8-Anwendung die HealthKit-API verwenden kann, muss sie ordnungsgemäß konfiguriert und bereitgestellt werden. In diesem Abschnitt werden die Schritte behandelt, die erforderlich sind, um Ihre Xamarin-Anwendung ordnungsgemäß einzurichten.

Health Kit-Apps erfordern:

  • Eine explizite App-ID.
  • Ein Bereitstellungsprofil , das dieser expliziten App-ID und den Berechtigungen des Health Kit zugeordnet ist.
  • Eine Entitlements.plist Eigenschaft mit festgelegter com.apple.developer.healthkit Typeigenschaft Boolean auf Yes.
  • Ein Info.plist Schlüssel, dessen UIRequiredDeviceCapabilities Schlüssel einen Eintrag mit dem String Wert healthkitenthält.
  • Die Info.plist erforderlichen Datenschutzerklärungseinträge müssen ebenfalls vorhanden sein: eine String Erklärung für den Schlüssel NSHealthUpdateUsageDescription , wenn die App Daten schreiben wird, und eine String Erklärung für den Schlüssel NSHealthShareUsageDescription , wenn die App Health Kit-Daten lesen wird.

Um mehr über die Bereitstellung einer iOS-App zu erfahren, beschreibt der Artikel "Gerätebereitstellung " in der Reihe "Erste Schritte " von Xamarin die Beziehung zwischen Entwicklerzertifikaten, App-IDs, Bereitstellungsprofilen und App-Berechtigungen.

Explizite App-ID und Bereitstellungsprofil

Die Erstellung einer expliziten App-ID und eines entsprechenden Bereitstellungsprofils erfolgt im iOS Dev Center von Apple.

Ihre aktuellen App-IDs werden im Abschnitt "Zertifikate, Bezeichner und Profile" im Dev Center aufgeführt. In dieser Liste werden häufig ID-Werte angezeigt, die angeben, dass der App-ID-Name - mit einer beliebigen Anzahl von Suffixen verwendet werden kann.* Solche Wild Karte App-IDs können nicht mit Health Kit verwendet werden.

Um eine explizite App-ID zu erstellen, klicken Sie oben rechts auf die + Schaltfläche, um Sie zur Seite "iOS-App-ID registrieren" zu bringen:

Registering an app on the Apple Developer Portal

Wie in der Abbildung oben gezeigt, verwenden Sie nach dem Erstellen einer App-Beschreibung den Abschnitt "Explizite App-ID ", um eine ID für Ihre Anwendung zu erstellen. Überprüfen Sie im Abschnitt "App Services" das Health Kit im Abschnitt "Enable Services".

Wenn Sie fertig sind, drücken Sie die Schaltfläche "Weiter ", um die App-ID in Ihrem Konto zu registrieren. Sie werden wieder auf die Seite "Zertifikate", "Bezeichner" und "Profile" zurückgebracht. Klicken Sie auf "Bereitstellungsprofile ", um Sie zur Liste Ihrer aktuellen Bereitstellungsprofile zu bringen, und klicken Sie in der oberen rechten Ecke auf die + Schaltfläche, um Sie zur Seite " iOS-Bereitstellungsprofil hinzufügen" zu bringen. Wählen Sie die Option "iOS-App-Entwicklung " aus, und klicken Sie auf " Weiter ", um zur Seite " App-ID auswählen" zu gelangen. Wählen Sie hier die explizite App-ID aus, die Sie zuvor angegeben haben:

Select the explicit App ID

Klicken Sie auf "Weiter", und arbeiten Sie durch die Standard Neuprüfungsbildschirme, in denen Sie Ihre Entwicklerzertifikate, Geräte und einen Namen für dieses Bereitstellungsprofil angeben:

Generating the Provisioning Profile

Klicken Sie auf "Generieren", und warten Sie die Erstellung Ihres Profils. Laden Sie die Datei herunter, und doppelklicken Sie darauf, um sie in Xcode zu installieren. Sie können bestätigen, dass die Installation unter Xcode-Einstellungen >> Konten > Details anzeigen... Ihr just-installiertes Bereitstellungsprofil sollte angezeigt werden, und es sollte über das Symbol für Das Health Kit und alle anderen speziellen Dienste in der Zeile "Berechtigungen" verfügen:

Viewing the profile in Xcode

Zuordnen der App-ID und des Bereitstellungsprofils zu Ihrer Xamarin.iOS-App

Nachdem Sie wie beschrieben ein entsprechendes Bereitstellungsprofil erstellt und installiert haben, ist es normalerweise an der Zeit, eine Lösung in Visual Studio für Mac oder Visual Studio zu erstellen. Der Health Kit-Zugriff ist für jedes iOS-C#- oder F#-Projekt verfügbar.

Anstatt den Prozess des Erstellens eines Xamarin iOS 8-Projekts manuell zu durchlaufen, öffnen Sie die an diesen Artikel angefügte Beispiel-App (einschließlich eines vordefinierten Storyboards und Codes). Um die Beispiel-App Ihrem Health Kit aktiviertes Bereitstellungsprofil zuzuordnen, klicken Sie im Lösungspad mit der rechten Maustaste auf Ihr Projekt, und rufen Sie das Dialogfeld "Optionen" auf. Wechseln Sie zum iOS-Anwendungsbereich, und geben Sie die explizite App-ID ein, die Sie zuvor als Bündelbezeichner der App erstellt haben:

Enter the explicit App ID

Wechseln Sie nun zum iOS-Bündelsignaturbereich . Ihr kürzlich installiertes Bereitstellungsprofil mit der Zuordnung zur expliziten App-ID ist jetzt als Bereitstellungsprofil verfügbar:

Select the Provisioning Profile

Wenn das Bereitstellungsprofil nicht verfügbar ist, überprüfen Sie den Bündelbezeichner im iOS-Anwendungsbereich im Vergleich zu dem im iOS Dev Center angegebenen Und dass das Bereitstellungsprofil installiert ist (Xcode-Einstellungen >>- und Kontoansichtsdetails>...).

Wenn das Health Kit-aktivierte Bereitstellungsprofil ausgewählt ist, klicken Sie auf "OK ", um das Dialogfeld "Projektoptionen" zu schließen.

Entitlements.plist- und Info.plist-Werte

Die Beispiel-App enthält eine Entitlements.plist Datei (die für Health Kit-aktivierte Apps erforderlich ist) und nicht in jeder Projektvorlage enthalten. Wenn Ihr Projekt keine Berechtigungen enthält, klicken Sie mit der rechten Maustaste auf Ihr Projekt, und wählen Sie "Datei > neue Datei" aus... > iOS-Berechtigungsliste.plist>, um ein Projekt manuell hinzuzufügen.

Letztendlich müssen Sie Entitlements.plist über das folgende Schlüssel- und Wertpaar verfügen:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.developer.HealthKit</key>
    <true/>
</dict>
</plist>

Entsprechend muss die Info.plist App einen Wert aufweisen, der healthkit dem UIRequiredDeviceCapabilities Schlüssel zugeordnet ist:

<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
    <string>healthkit</string>
</array>

Die beispielanwendung, die mit diesem Artikel bereitgestellt wird, enthält eine vorkonfigurierte Entitlements.plist Anwendung, die alle erforderlichen Schlüssel enthält.

Programming Health Kit

Der Health Kit-Datenspeicher ist ein privater, benutzerspezifischer Datenspeicher, der für Apps freigegeben wird. Da Integritätsinformationen so vertraulich sind, muss der Benutzer positive Schritte ausführen, um den Datenzugriff zu ermöglichen. Dieser Zugriff kann teilweise sein (schreibgeschützt, aber nicht gelesen, Zugriff auf einige Arten von Daten, aber nicht andere usw.) und kann jederzeit widerrufen werden. Health Kit-Anwendungen sollten defensiv geschrieben werden, mit dem Verständnis, dass viele Benutzer zögern werden, ihre gesundheitsbezogenen Informationen zu speichern.

Health Kit-Daten sind auf bestimmte Apple-Typen beschränkt. Diese Typen sind streng definiert: einige, z. B. Bluttyp, sind auf die spezifischen Werte einer von Apple bereitgestellten Enumeration beschränkt, während andere eine Größe mit einer Maßeinheit (wie Gramm, Kalorien und Liter) kombinieren. Auch Daten, die eine kompatible Maßeinheit gemeinsam nutzen, werden durch ihre HKObjectTypeUnterschieden unterschieden. So wird z. B. das Typsystem einen fehlerhaften Versuch abfangen, einen HKQuantityTypeIdentifier.NumberOfTimesFallen Wert in einem Feld zu speichern, das eine HKQuantityTypeIdentifier.FlightsClimbed Maßeinheit erwartet, obwohl beide die HKUnit.Count Maßeinheit verwenden.

Die im Health Kit-Datenspeicher verfügbaren Typen sind alle Unterklassen von HKObjectType. HKCharacteristicType Objekte speichern biologisches Geschlecht, Bluttyp und Geburtsdatum. Häufiger sind HKSampleType jedoch Objekte, die Daten darstellen, die zu einem bestimmten Zeitpunkt oder über einen bestimmten Zeitraum stichprobeniert werden.

HKSampleType objects chart

HKSampleType ist abstrahiert und hat vier konkrete Unterklassen. Zurzeit gibt es nur einen Datentyp, bei dem es sich um die HKCategoryType Schlafanalyse handelt. Die meisten Daten im Health Kit sind vom Typ und HKQuantityType speichern ihre Daten in HKQuantitySample Objekten, die mit dem vertrauten Factory-Entwurfsmuster erstellt werden:

The large majority of data in Health Kit are of type HKQuantityType and store their data in HKQuantitySample objects

HKQuantityType Typen reichen von HKQuantityTypeIdentifier.ActiveEnergyBurned bis zu HKQuantityTypeIdentifier.StepCount.

Anfordern der Berechtigung vom Benutzer

Endbenutzer müssen positive Schritte ausführen, damit eine App Health Kit-Daten lesen oder schreiben kann. Dies erfolgt über die Integritäts-App, die auf iOS 8-Geräten vorinstalliert ist. Wenn eine Health Kit-App zum ersten Mal ausgeführt wird, wird dem Benutzer ein systemgesteuertes Dialogfeld für den Integritätszugriff angezeigt:

The user is presented with a system-controlled Health Access dialog

Später kann der Benutzer Berechtigungen mithilfe des Dialogfelds "Quellen" der Integritäts-App ändern:

The user can change permissions using Health apps Sources dialog

Da Integritätsinformationen extrem vertraulich sind, sollten App-Entwickler ihre Programme defensiv schreiben, wobei erwartet wird, dass Berechtigungen abgelehnt und geändert werden, während die App ausgeführt wird. Das am häufigsten verwendete Idiom besteht darin, Berechtigungen in der UIApplicationDelegate.OnActivated Methode anzufordern und dann die Benutzeroberfläche entsprechend zu ändern.

Exemplarische Vorgehensweise für Berechtigungen

Öffnen Sie die AppDelegate.cs Datei in Ihrem Von Health Kit bereitgestellten Projekt. Beachten Sie die Anweisung mit HealthKit; am Anfang der Datei.

Der folgende Code bezieht sich auf Health Kit-Berechtigungen:

private HKHealthStore healthKitStore = new HKHealthStore ();

public override void OnActivated (UIApplication application)
{
        base.OnActivated(application);
        ValidateAuthorization ();
}

private void ValidateAuthorization ()
{
        var heartRateId = HKQuantityTypeIdentifierKey.HeartRate;
        var heartRateType = HKObjectType.GetQuantityType (heartRateId);
        var typesToWrite = new NSSet (new [] { heartRateType });
        var typesToRead = new NSSet ();
        healthKitStore.RequestAuthorizationToShare (
                typesToWrite, 
                typesToRead, 
                ReactToHealthCarePermissions);
}

void ReactToHealthCarePermissions (bool success, NSError error)
{
        var access = healthKitStore.GetAuthorizationStatus (HKObjectType.GetQuantityType (HKQuantityTypeIdentifierKey.HeartRate));
        if (access.HasFlag (HKAuthorizationStatus.SharingAuthorized)) {
                HeartRateModel.Instance.Enabled = true;
        } else {
                HeartRateModel.Instance.Enabled = false;
        }
}

Der gesamte Code in diesen Methoden kann inline OnActivatedausgeführt werden. Die Beispiel-App verwendet jedoch separate Methoden, um ihre Absicht deutlicher zu machen: ValidateAuthorization() Hat die Schritte, die erforderlich sind, um den Zugriff auf die spezifischen Typen anzufordern, die geschrieben werden (und lesen, wenn die App gewünscht wird) und ReactToHealthCarePermissions() ein Rückruf ist, der aktiviert wird, nachdem der Benutzer mit dem Berechtigungsdialogfeld in der Health.app interagiert hat.

Der Auftrag ValidateAuthorization() besteht darin, den Satz davon HKObjectTypes zu erstellen, dass die App schreibt und eine Autorisierung anfordert, um diese Daten zu aktualisieren. In der Beispiel-App gilt der HKObjectType Schlüssel KHQuantityTypeIdentifierKey.HeartRate. Dieser Typ wird dem Satz hinzugefügt, während der Satz typesToWritetypesToRead leer bleibt. Diese Sätze und ein Verweis auf den ReactToHealthCarePermissions() Rückruf werden an übergeben HKHealthStore.RequestAuthorizationToShare().

Der ReactToHealthCarePermissions() Rückruf wird aufgerufen, nachdem der Benutzer mit dem Berechtigungsdialogfeld interagiert hat und zwei Informationen übergeben wird: ein bool Wert, der sein true wird, wenn der Benutzer mit dem Berechtigungsdialogfeld interagiert hat, und ein NSError Fehler, der, wenn nicht null, eine Art von Fehler anzeigt, der mit der Darstellung des Berechtigungsdialogfelds verknüpft ist.

Wichtig

Um über die Argumente für diese Funktion klar zu sein: Die Erfolgs - und Fehlerparameter geben nicht an, ob der Benutzer die Berechtigung für den Zugriff auf Health Kit-Daten erteilt hat! Sie geben nur an, dass dem Benutzer die Möglichkeit gegeben wurde, den Zugriff auf die Daten zu ermöglichen.

Um zu bestätigen, ob die App Zugriff auf die Daten hat, wird sie HKHealthStore.GetAuthorizationStatus() verwendet und übergeben HKQuantityTypeIdentifierKey.HeartRate. Basierend auf dem zurückgegebenen Status aktiviert oder deaktiviert die App die Möglichkeit, Daten einzugeben. Es gibt keine Standardmäßige Benutzeroberfläche für den Umgang mit einer Zugriffsverweigerung, und es gibt viele mögliche Optionen. In der Beispiel-App wird der Status für ein HeartRateModel Singleton-Objekt festgelegt, das wiederum relevante Ereignisse auslöst.

Modell, Ansicht und Controller

Um das HeartRateModel Singleton-Objekt zu überprüfen, öffnen Sie die HeartRateModel.cs Datei:

using System;
using HealthKit;
using Foundation;

namespace HKWork
{
        public class GenericEventArgs<T> : EventArgs
        {
                public T Value { get; protected set; }
                public DateTime Time { get; protected set; }

                public GenericEventArgs (T value)
                {
                        this.Value = value;
                        Time = DateTime.Now;
                }
        }

        public delegate void GenericEventHandler<T> (object sender,GenericEventArgs<T> args);

        public sealed class HeartRateModel : NSObject
        {
                private static volatile HeartRateModel singleton;
                private static object syncRoot = new Object ();

                private HeartRateModel ()
                {
                }

                public static HeartRateModel Instance {
                        get {
                                //Double-check lazy initialization
                                if (singleton == null) {
                                        lock (syncRoot) {
                                                if (singleton == null) {
                                                        singleton = new HeartRateModel ();
                                                }
                                        }
                                }

                                return singleton;
                        }
                }

                private bool enabled = false;

                public event GenericEventHandler<bool> EnabledChanged;
                public event GenericEventHandler<String> ErrorMessageChanged;
                public event GenericEventHandler<Double> HeartRateStored;

                public bool Enabled { 
                        get { return enabled; }
                        set {
                                if (enabled != value) {
                                        enabled = value;
                                        InvokeOnMainThread(() => EnabledChanged (this, new GenericEventArgs<bool>(value)));
                                }
                        }
                }

                public void PermissionsError(string msg)
                {
                        Enabled = false;
                        InvokeOnMainThread(() => ErrorMessageChanged (this, new GenericEventArgs<string>(msg)));
                }

                //Converts its argument into a strongly-typed quantity representing the value in beats-per-minute
                public HKQuantity HeartRateInBeatsPerMinute(ushort beatsPerMinute)
                {
                        var heartRateUnitType = HKUnit.Count.UnitDividedBy (HKUnit.Minute);
                        var quantity = HKQuantity.FromQuantity (heartRateUnitType, beatsPerMinute);

                        return quantity;
                }
                        
                public void StoreHeartRate(HKQuantity quantity)
                {
                        var bpm = HKUnit.Count.UnitDividedBy (HKUnit.Minute);
                        //Confirm that the value passed in is of a valid type (can be converted to beats-per-minute)
                        if (! quantity.IsCompatible(bpm))
                        {
                                InvokeOnMainThread(() => ErrorMessageChanged(this, new GenericEventArgs<string> ("Units must be compatible with BPM")));
                        }

                        var heartRateId = HKQuantityTypeIdentifierKey.HeartRate;
                        var heartRateQuantityType = HKQuantityType.GetQuantityType (heartRateId);
                        var heartRateSample = HKQuantitySample.FromType (heartRateQuantityType, quantity, new NSDate (), new NSDate (), new HKMetadata());

                        using (var healthKitStore = new HKHealthStore ()) {
                                healthKitStore.SaveObject (heartRateSample, (success, error) => {
                                        InvokeOnMainThread (() => {
                                                if (success) {
                                                        HeartRateStored(this, new GenericEventArgs<Double>(quantity.GetDoubleValue(bpm)));
                                                } else {
                                                        ErrorMessageChanged(this, new GenericEventArgs<string>("Save failed"));
                                                }
                                                if (error != null) {
                                                        //If there's some kind of error, disable 
                                                        Enabled = false;
                                                        ErrorMessageChanged (this, new GenericEventArgs<string>(error.ToString()));
                                                }
                                        });
                                });
                        }
                }
        }
}

Der erste Abschnitt ist Codebausteine zum Erstellen generischer Ereignisse und Handler. Der anfängliche Teil der HeartRateModel Klasse ist auch Einbaustein zum Erstellen eines threadsicheren Singletonobjekts.

HeartRateModel Anschließend werden drei Ereignisse verfügbar gemacht:

  • EnabledChanged - Gibt an, dass der Herzfrequenzspeicher aktiviert oder deaktiviert wurde (beachten Sie, dass der Speicher anfänglich deaktiviert ist).
  • ErrorMessageChanged - Für diese Beispiel-App gibt es ein sehr einfaches Fehlerbehandlungsmodell: eine Zeichenfolge mit dem letzten Fehler.
  • HeartRateStored – Wird ausgelöst, wenn eine Herzfrequenz in der Health Kit-Datenbank gespeichert wird.

Beachten Sie, dass es immer dann erfolgt, wenn diese Ereignisse ausgelöst werden, über NSObject.InvokeOnMainThread()die Abonnenten die Benutzeroberfläche aktualisieren können. Alternativ können die Ereignisse so dokumentiert werden, dass sie in Hintergrundthreads ausgelöst werden, und die Verantwortung, die Kompatibilität sicherzustellen, ihren Handlern überlassen werden könnte. Threadüberlegungen sind in Health Kit-Anwendungen wichtig, da viele der Funktionen, z. B. die Berechtigungsanforderung, asynchron sind und ihre Rückrufe für Nicht-Standard Threads ausführen.

Der spezifische Heath Kit-Code in HeartRateModel den beiden Funktionen HeartRateInBeatsPerMinute() und StoreHeartRate().

HeartRateInBeatsPerMinute() konvertiert das Argument in ein stark typiertes Health Kit HKQuantity. Der Typ der Menge ist, dass durch die HKQuantityTypeIdentifierKey.HeartRate und die Einheiten der Menge dividiert HKUnit.Minute werden HKUnit.Count (mit anderen Worten, die Einheit wird pro Minute schlagen).

Die StoreHeartRate() Funktion verwendet eine HKQuantity (in der Beispiel-App, von der eine erstellt wurde HeartRateInBeatsPerMinute() ). Um die Daten zu überprüfen, verwendet sie die HKQuantity.IsCompatible() Methode, die zurückgibt true , ob die Einheiten des Objekts in die Einheiten im Argument konvertiert werden können. Wenn die Menge mit HeartRateInBeatsPerMinute() dieser Erstellt wurde, wird offensichtlich zurückgegeben true, aber sie würde auch zurückgeben true , wenn die Menge erstellt wurde, z . B. Beats per Hour. Im Allgemeinen kann verwendet werden, HKQuantity.IsCompatible() um Masse, Entfernung und Energie zu überprüfen, die der Benutzer oder ein Gerät in einem Messsystem (z. B. Imperiale Einheiten) eingeben oder anzeigen kann, das jedoch in einem anderen System (z. B. Metrikeinheiten) gespeichert werden kann.

Nachdem die Kompatibilität der Menge überprüft wurde, wird die HKQuantitySample.FromType() Factorymethode verwendet, um ein stark typiertes heartRateSample Objekt zu erstellen. HKSample Objekte haben ein Anfangs- und Enddatum; bei sofortigen Lesewerten sollten diese Werte identisch sein, wie sie sich im Beispiel befinden. Im Beispiel werden auch keine Schlüsselwertdaten in ihrem HKMetadata Argument festgelegt, aber ein Code wie der folgende Code kann zum Angeben der Sensorposition verwendet werden:

var hkm = new HKMetadata();
hkm.HeartRateSensorLocation = HKHeartRateSensorLocation.Chest;

Nachdem der heartRateSample Code erstellt wurde, erstellt der Code eine neue Verbindung mit der Datenbank mit dem using-Block. Innerhalb dieses Blocks versucht die HKHealthStore.SaveObject() Methode den asynchronen Schreibvorgang in die Datenbank. Der resultierende Aufruf des Lambda-Ausdrucks löst relevante Ereignisse aus, entweder HeartRateStored oder ErrorMessageChanged.

Nachdem das Modell programmiert wurde, ist es an der Zeit, zu sehen, wie der Controller den Zustand des Modells widerspiegelt. Öffnen Sie die Datei HKWorkViewController.cs. Der Konstruktor verkabelt einfach das HeartRateModel Singleton mit Ereignisbehandlungsmethoden (auch hier könnte dies inline mit Lambda-Ausdrücken erfolgen, aber separate Methoden machen die Absicht etwas offensichtlicher):

public HKWorkViewController (IntPtr handle) : base (handle)
{
     HeartRateModel.Instance.EnabledChanged += OnEnabledChanged;
     HeartRateModel.Instance.ErrorMessageChanged += OnErrorMessageChanged;
     HeartRateModel.Instance.HeartRateStored += OnHeartBeatStored;
}

Hier sind die relevanten Handler:

void OnEnabledChanged (object sender, GenericEventArgs<bool> args)
{
        StoreData.Enabled = args.Value;
        PermissionsLabel.Text = args.Value ? "Ready to record" : "Not authorized to store data.";
        PermissionsLabel.SizeToFit ();
}

void OnErrorMessageChanged (object sender, GenericEventArgs<string> args)
{
        PermissionsLabel.Text = args.Value;
}

void OnHeartBeatStored (object sender, GenericEventArgs<double> args)
{
        PermissionsLabel.Text = String.Format ("Stored {0} BPM", args.Value);
}

Offensichtlich wäre es in einer Anwendung mit einem einzigen Controller möglich, die Erstellung eines separaten Modellobjekts und die Verwendung von Ereignissen für den Steuerungsfluss zu vermeiden, aber die Verwendung von Modellobjekten ist für reale Apps besser geeignet.

Ausführen der Beispiel-App

Der iOS-Simulator unterstützt das Health Kit nicht. Das Debuggen muss auf einem physischen Gerät unter iOS 8 erfolgen.

Fügen Sie ein ordnungsgemäß bereitgestelltes iOS 8-Entwicklungsgerät an Ihr System an. Wählen Sie es als Bereitstellungsziel in Visual Studio für Mac aus, und wählen Sie im Menü "Debuggen ausführen" >aus.

Wichtig

Fehler im Zusammenhang mit der Bereitstellung werden zu diesem Zeitpunkt angezeigt. Wenn Sie Fehler beheben möchten, lesen Sie den Abschnitt "Erstellen und Bereitstellen einer Health Kit-App" weiter oben. Die Komponenten sind:

  • iOS Dev Center – Explizite App-ID & Health Kit aktiviert Bereitstellungsprofil.
  • Project-Optionen – Bündelbezeichner (explizite App-ID) und Bereitstellungsprofil.
  • Quellcode - Entitlements.plist & Info.plist

Vorausgesetzt, dass Die Bestimmungen ordnungsgemäß festgelegt wurden, wird ihre Anwendung gestartet. Wenn sie die OnActivated Methode erreicht, fordert sie die Health Kit-Autorisierung an. Wenn dies zum ersten Mal vom Betriebssystem auftritt, wird Dem Benutzer das folgende Dialogfeld angezeigt:

The user will be presented with this dialog

Aktivieren Sie Ihre App, Um Heart Rate-Daten zu aktualisieren, und Ihre App wird wieder angezeigt. Der ReactToHealthCarePermissions Rückruf wird asynchron aktiviert. Dadurch wird die HeartRateModel’sEnabled Eigenschaft geändert, wodurch das EnabledChanged Ereignis ausgelöst wird, wodurch der HKPermissionsViewController.OnEnabledChanged() Ereignishandler ausgeführt wird, wodurch die StoreData Schaltfläche aktiviert wird. Das folgende Diagramm zeigt die Sequenz:

This diagram shows the sequence of events

Drücken Sie die Schaltfläche "Datensatz ". Dadurch wird der StoreData_TouchUpInside() Handler ausgeführt, der versucht, den Wert des heartRate Textfelds zu analysieren, in eine HKQuantity über die zuvor erläuterte HeartRateModel.HeartRateInBeatsPerMinute() Funktion zu konvertieren und diese Menge an .HeartRateModel.StoreHeartRate() Wie bereits erwähnt, versucht dies, die Daten zu speichern und löst entweder ein Ereignis oder ErrorMessageChanged ein HeartRateStored Ereignis aus.

Doppelklicken Sie auf die Schaltfläche "Start " auf Ihrem Gerät, und öffnen Sie die Integritäts-App. Klicken Sie auf die Registerkarte "Quellen ", und die Beispiel-App wird aufgelistet. Wählen Sie es aus, und verbieten Sie die Berechtigung, Herzfrequenzdaten zu aktualisieren. Doppelklicken Sie auf die Schaltfläche "Start ", und wechseln Sie zurück zu Ihrer App. Wird erneut ReactToHealthCarePermissions() aufgerufen, aber diesmal, da der Zugriff verweigert wird, wird die StoreData-Schaltfläche deaktiviert (beachten Sie, dass dies asynchron erfolgt und die Änderung auf der Benutzeroberfläche für den Endbenutzer sichtbar sein kann).

Fortgeschrittene Themen

Das Lesen von Daten aus der Health Kit-Datenbank ist dem Schreiben von Daten sehr ähnlich: Einer gibt die Datentypen an, auf die zugegriffen werden soll, fordert autorisierung an, und wenn diese Autorisierung gewährt wird, sind die Daten verfügbar, mit der automatischen Konvertierung in kompatible Maßeinheiten.

Es gibt eine Reihe komplexerer Abfragefunktionen, die prädikatbasierte Abfragen und Abfragen zulassen, die Aktualisierungen ausführen, wenn relevante Daten aktualisiert werden.

Entwickler von Health Kit-Anwendungen sollten den Abschnitt "Health Kit" der App-Überprüfungsrichtlinien von Apple überprüfen.

Sobald die Sicherheits- und Typsystemmodelle verstanden werden, ist das Speichern und Lesen von Daten in der freigegebenen Health Kit-Datenbank recht einfach. Viele der Funktionen im Health Kit funktionieren asynchron, und Anwendungsentwickler müssen ihre Programme entsprechend schreiben.

Ab dem Schreiben dieses Artikels gibt es derzeit kein Äquivalent zum Health Kit in Android oder Windows Telefon.

Zusammenfassung

In diesem Artikel haben wir erfahren, wie Das Health Kit Anwendungen das Speichern, Abrufen und Freigeben von Informationen im Zusammenhang mit dem Integritätsstatus ermöglicht, und gleichzeitig eine Standard-Integritäts-App bereitstellt, die dem Benutzer den Zugriff und die Kontrolle über diese Daten ermöglicht.

Außerdem haben wir gesehen, wie Datenschutz, Sicherheit und Datenintegrität Bedenken für gesundheitsbezogene Informationen und Apps mit Health Kit überschreiben müssen, um die Komplexität bei Anwendungsverwaltungsaspekten (Bereitstellung), Codierung (Systemtypsystem des Health Kit) und Benutzerfreundlichkeit (Benutzersteuerung von Berechtigungen über Systemdialogfeld und Integritäts-App) zu bewältigen.

Schließlich werfen wir einen Blick auf eine einfache Implementierung des Health Kit mithilfe der enthaltenen Beispiel-App, die Taktdaten in den Health Kit-Speicher schreibt und über ein asynchrones Design verfügt.