Udostępnij za pośrednictwem


Zestaw kondycji w środowisku Xamarin.iOS

Zestaw Health Kit udostępnia bezpieczny magazyn danych dla informacji związanych z kondycją użytkownika. Aplikacje zestawu Health Kit mogą mieć jawne uprawnienia użytkownika, odczytywać i zapisywać w tym magazynie danych i otrzymywać powiadomienia po dodaniu odpowiednich danych. Aplikacje mogą prezentować dane lub użytkownik może używać udostępnionej przez firmę Apple aplikacji Health do wyświetlania pulpitu nawigacyjnego wszystkich swoich danych.

Ponieważ dane dotyczące zdrowia są tak wrażliwe i kluczowe, zestaw health kit jest silnie typizowane, z jednostkami miary i wyraźnym skojarzeniem z typem rejestrowanych informacji (na przykład poziom glukozy we krwi lub tętno). Ponadto aplikacje zestawu Health Kit muszą używać jawnych uprawnień, muszą żądać dostępu do określonych typów informacji, a użytkownik musi jawnie udzielić aplikacji dostępu do tych typów danych.

W tym artykule przedstawiono następujące elementy:

  • Wymagania dotyczące zabezpieczeń zestawu Health Kit, w tym aprowizowanie aplikacji i żądanie uprawnień użytkownika w celu uzyskania dostępu do bazy danych zestawu Health Kit;
  • System typów zestawu Health Kit, który minimalizuje możliwość błędnego stosowania lub błędnego interpretowania danych;
  • Zapisywanie w udostępnionym magazynie danych zestawu Health Kit dla całego systemu.

W tym artykule nie omówiono bardziej zaawansowanych tematów, takich jak wykonywanie zapytań dotyczących bazy danych, konwertowanie między jednostkami miary lub otrzymywanie powiadomień o nowych danych.

W tym artykule utworzymy przykładową aplikację do rejestrowania tętna użytkownika:

Przykładowa aplikacja do rejestrowania tętna użytkowników

Wymagania

Do wykonania kroków przedstawionych w tym artykule są wymagane następujące czynności:

  • Xcode 7 i iOS 8 (lub nowsze) — najnowsze interfejsy API Xcode i iOS firmy Apple muszą być zainstalowane i skonfigurowane na komputerze dewelopera.
  • Visual Studio dla komputerów Mac lub Visual Studio — najnowszą wersję Visual Studio dla komputerów Mac należy zainstalować i skonfigurować na komputerze dewelopera.
  • Urządzenie z systemem iOS 8 (lub nowszym) — urządzenie z systemem iOS z najnowszą wersją systemu iOS 8 lub nowszego na potrzeby testowania.

Ważne

Zestaw Health Kit został wprowadzony w systemie iOS 8. Obecnie zestaw Health Kit nie jest dostępny w symulatorze systemu iOS, a debugowanie wymaga połączenia z fizycznym urządzeniem z systemem iOS.

Tworzenie i aprowizowanie aplikacji zestawu kondycji

Aby aplikacja platformy Xamarin dla systemu iOS 8 mogła korzystać z interfejsu API zestawu HealthKit, musi być prawidłowo skonfigurowana i aprowizowana. W tej sekcji omówiono kroki wymagane do prawidłowego skonfigurowania aplikacji platformy Xamarin.

Aplikacje zestawu Health Kit wymagają:

  • Jawny identyfikator aplikacji.
  • Profil aprowizacji skojarzony z tym jawnym identyfikatorem aplikacji i uprawnieniami zestawu kondycji.
  • Obiekt Entitlements.plist z właściwością typu Boolean ustawioną com.apple.developer.healthkit na Yes.
  • Element, którego Info.plist UIRequiredDeviceCapabilities klucz zawiera wpis z wartością healthkitString .
  • Musi Info.plist również mieć odpowiednie wpisy wyjaśnienia prywatności: String wyjaśnienie klucza NSHealthUpdateUsageDescription , jeśli aplikacja będzie zapisywać dane i String wyjaśnienie klucza NSHealthShareUsageDescription , jeśli aplikacja będzie odczytywać dane zestawu Health Kit.

Aby dowiedzieć się więcej na temat aprowizacji aplikacji systemu iOS, artykuł Device Provisioning w serii Wprowadzenie platformy Xamarin opisuje relację między certyfikatami deweloperów, identyfikatorami aplikacji, profilami aprowizacji i uprawnieniami aplikacji.

Jawny identyfikator aplikacji i profil aprowizacji

Tworzenie jawnego identyfikatora aplikacji i odpowiedniego profilu aprowizacji odbywa się w Centrum deweloperów systemu iOS firmy Apple.

Bieżące identyfikatory aplikacji są wyświetlane w sekcji Certyfikaty, Identyfikatory i profile Centrum deweloperów. Często na tej liście będą wyświetlane wartości identyfikatorów * , które wskazują, że nazwa identyfikatora - aplikacji może być używana z dowolną liczbą sufiksów. Takich identyfikatorów aplikacji wieloznacznych nie można używać z zestawem Health Kit.

Aby utworzyć jawny identyfikator aplikacji, kliknij + przycisk w prawym górnym rogu, aby otworzyć stronę Rejestrowanie identyfikatora aplikacji systemu iOS:

Rejestrowanie aplikacji w portalu dla deweloperów firmy Apple

Jak pokazano na powyższym obrazie, po utworzeniu opisu aplikacji użyj sekcji Jawny identyfikator aplikacji, aby utworzyć identyfikator aplikacji. W sekcji App Services sprawdź zestaw kondycji w sekcji Włączanie usług.

Po zakończeniu naciśnij przycisk Kontynuuj , aby zarejestrować identyfikator aplikacji na swoim koncie. Nastąpi powrót do strony Certyfikaty, Identyfikatory i Profile . Kliknij pozycję Profile aprowizacji, aby wyświetlić listę bieżących profilów aprowizacji, a następnie kliknij + przycisk w prawym górnym rogu, aby otworzyć stronę Dodawanie profilu aprowizacji systemu iOS. Wybierz opcję Tworzenie aplikacji systemu iOS i kliknij przycisk Kontynuuj, aby przejść do strony Wybierz identyfikator aplikacji. W tym miejscu wybierz jawny identyfikator aplikacji, który został wcześniej określony:

Wybierz jawny identyfikator aplikacji

Kliknij przycisk Kontynuuj i przejdź do pozostałych ekranów, na których określisz certyfikaty dewelopera, urządzenia i nazwę dla tego profilu aprowizacji:

Generowanie profilu aprowizacji

Kliknij pozycję Generuj i poczekaj na utworzenie profilu. Pobierz plik i kliknij go dwukrotnie, aby zainstalować w programie Xcode. Możesz potwierdzić, że jest ona instalowana w obszarze Konta > preferencji > Xcode > Wyświetl szczegóły... Powinien zostać wyświetlony właśnie zainstalowany profil aprowizacji i powinien mieć ikonę Zestawu kondycji i innych specjalnych usług w wierszu Upoważnienia:

Wyświetlanie profilu w programie Xcode

Kojarzenie identyfikatora aplikacji i profilu aprowizacji z aplikacją platformy Xamarin.iOS

Po utworzeniu i zainstalowaniu odpowiedniego profilu aprowizacji zgodnie z opisem zwykle należy utworzyć rozwiązanie w programie Visual Studio dla komputerów Mac lub Visual Studio. Dostęp do zestawu Health Kit jest dostępny dla dowolnego projektu w języku C# lub F# dla systemu iOS.

Zamiast przechodzić przez proces tworzenia projektu platformy Xamarin dla systemu iOS 8 ręcznie, otwórz przykładową aplikację dołączoną do tego artykułu (zawierającą wstępnie skompilowany scenorys i kod). Aby skojarzyć przykładową aplikację z profilem aprowizacji zestawu kondycji, w okienku rozwiązania kliknij prawym przyciskiem myszy projekt i wyświetl okno dialogowe Opcje. Przejdź do panelu Aplikacja systemu iOS i wprowadź jawny identyfikator aplikacji utworzony wcześniej jako identyfikator pakietu aplikacji:

Wprowadź jawny identyfikator aplikacji

Teraz przejdź do panelu podpisywania pakietu systemu iOS. Ostatnio zainstalowany profil aprowizacji ze skojarzeniem z jawnym identyfikatorem aplikacji będzie teraz dostępny jako profil aprowizacji:

Wybierz profil aprowizacji

Jeśli profil aprowizacji jest niedostępny, sprawdź dwukrotnie identyfikator pakietu w panelu aplikacji systemu iOS w porównaniu z określonym w Centrum deweloperów systemu iOS i czy profil aprowizacji jest zainstalowany (konta > preferencji > Xcode > Wyświetl szczegóły...).

Po wybraniu profilu aprowizacji z obsługą zestawu kondycji kliknij przycisk OK, aby zamknąć okno dialogowe Opcje projektu.

Entitlements.plist i Info.plist Values

Przykładowa aplikacja zawiera plik (który jest niezbędny dla aplikacji z obsługą Entitlements.plist zestawu kondycji) i nie jest uwzględniony w każdym szablonie projektu. Jeśli projekt nie zawiera uprawnień, kliknij prawym przyciskiem myszy projekt, wybierz pozycję Plik > nowy plik... > iOS > Entitlements.plist , aby dodać jeden ręcznie.

Ostatecznie musisz Entitlements.plist mieć następującą parę klucz i wartość:

<?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>

Podobnie dla Info.plist aplikacji musi mieć wartość healthkit skojarzona z kluczem UIRequiredDeviceCapabilities :

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

Przykładowa aplikacja udostępniona w tym artykule zawiera wstępnie skonfigurowaną Entitlements.plist aplikację zawierającą wszystkie wymagane klucze.

Zestaw kondycji programowania

Magazyn danych zestawu Health Kit to prywatny magazyn danych specyficzny dla użytkownika, który jest współużytkowany przez aplikacje. Ponieważ informacje o kondycji są tak wrażliwe, użytkownik musi wykonać pozytywne kroki, aby zezwolić na dostęp do danych. Ten dostęp może być częściowy (zapis, ale nie odczyt, dostęp do niektórych typów danych, ale nie innych itp.) i może zostać odwołany w dowolnym momencie. Aplikacje zestawu Health Kit powinny być napisane defensywnie, z zrozumieniem, że wielu użytkowników będzie niezdecydowany o przechowywaniu ich informacji związanych z zdrowiem.

Dane zestawu Health Kit są ograniczone do określonych typów firmy Apple. Typy te są ściśle zdefiniowane: niektóre, takie jak typ krwi, są ograniczone do konkretnych wartości wyliczenia dostarczonego przez Apple, podczas gdy inne łączą wielkość z jednostką miary (taką jak gramy, kalorie i litry). Nawet dane, które współużytkują zgodną jednostkę miary, są rozróżniane przez HKObjectTypeelement ; na przykład system typów przechwyci błędną próbę zapisania HKQuantityTypeIdentifier.NumberOfTimesFallen wartości w polu oczekiwanym HKQuantityTypeIdentifier.FlightsClimbed , mimo że oba te elementy używają HKUnit.Count jednostki miary.

Typy, które można przechowywać w magazynie danych zestawu Health Kit, to wszystkie podklasy .HKObjectType HKCharacteristicType obiekty przechowują biologiczną płeć, typ krwi i datę urodzenia. Częściej jednak są to HKSampleType obiekty reprezentujące dane, które są próbkowane w określonym czasie lub w określonym czasie.

Wykres obiektów HKSampleType

HKSampleType jest abstrakcyjna i ma cztery podklasy betonowe. Obecnie istnieje tylko jeden typ HKCategoryType danych, czyli analiza snu. Większość danych w zestawie Health Kit jest typu HKQuantityType i przechowuje dane w HKQuantitySample obiektach, które są tworzone przy użyciu znanego wzorca projektowania fabryki:

Duża większość danych w zestawie Health Kit jest typu HKQuantityType i przechowuje swoje dane w obiektach HKQuantitySample

HKQuantityType typy wahają się od HKQuantityTypeIdentifier.ActiveEnergyBurned do HKQuantityTypeIdentifier.StepCount.

Żądanie uprawnień od użytkownika

Użytkownicy końcowi muszą wykonać pozytywne kroki, aby umożliwić aplikacji odczytywanie lub zapisywanie danych zestawu Health Kit. Odbywa się to za pośrednictwem aplikacji Kondycja, która jest wstępnie zainstalowana na urządzeniach z systemem iOS 8. Przy pierwszym uruchomieniu aplikacji zestawu kondycji użytkownik jest wyświetlany w oknie dialogowym dostępu do kondycji kontrolowanym przez system:

Użytkownik jest wyświetlany w oknie dialogowym dostępu do kondycji kontrolowanym przez system

Później użytkownik może zmienić uprawnienia przy użyciu okna dialogowego Źródła aplikacji kondycji:

Użytkownik może zmienić uprawnienia przy użyciu okna dialogowego Źródła aplikacji kondycji

Ponieważ informacje o kondycji są bardzo wrażliwe, deweloperzy aplikacji powinni pisać swoje programy w defensywie, z oczekiwaniami, że uprawnienia zostaną odrzucone i zmienione podczas działania aplikacji. Najczęstszym idiomem jest zażądanie uprawnień w metodzie UIApplicationDelegate.OnActivated , a następnie zmodyfikowanie interfejsu użytkownika zgodnie z potrzebami.

Przewodnik po uprawnieniach

W projekcie aprowizacji zestawu kondycji AppDelegate.cs otwórz plik. Zwróć uwagę na instrukcję using HealthKit; w górnej części pliku.

Poniższy kod odnosi się do uprawnień zestawu Health Kit:

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;
        }
}

Cały kod w tych metodach można wykonać w tekście w OnActivatedpliku , ale przykładowa aplikacja używa oddzielnych metod, aby ich intencja była jaśniejsza: ValidateAuthorization() zawiera kroki niezbędne do żądania dostępu do zapisanych typów (i odczytywania, jeśli aplikacja jest wymagana) i ReactToHealthCarePermissions() jest wywołaniem zwrotnym aktywowanym po interakcji użytkownika z okna dialogowego uprawnień w Health.app.

Zadaniem programu ValidateAuthorization() jest skompilowanie zestawu HKObjectTypes , który aplikacja będzie zapisywać i żądać autoryzacji w celu zaktualizowania tych danych. W przykładowej aplikacji parametr HKObjectType jest przeznaczony dla klucza KHQuantityTypeIdentifierKey.HeartRate. Ten typ jest dodawany do zestawu typesToWrite, a zestaw typesToRead jest pozostawiony pusty. Te zestawy i odwołanie do wywołania zwrotnego ReactToHealthCarePermissions() są przekazywane do HKHealthStore.RequestAuthorizationToShare()elementu .

Wywołanie ReactToHealthCarePermissions() zwrotne będzie wywoływane po interakcji użytkownika z okna dialogowego uprawnień i przekazuje dwie informacje: bool wartość, która będzie mieć wartość, która będzie true , jeśli użytkownik wchodził w interakcję z okna dialogowego uprawnień i NSError który, jeśli nie ma wartości null, wskazuje jakiś błąd związany z prezentowaniem okna dialogowego uprawnień.

Ważne

Aby wyjaśnić argumenty tej funkcji: parametry powodzenia i błędu nie wskazują, czy użytkownik udzielił uprawnień dostępu do danych zestawu Health Kit! Wskazują one tylko, że użytkownik otrzymał możliwość zezwolenia na dostęp do danych.

Aby potwierdzić, czy aplikacja ma dostęp do danych, HKHealthStore.GetAuthorizationStatus() jest używana, przekazując element HKQuantityTypeIdentifierKey.HeartRate. Na podstawie zwróconego stanu aplikacja włącza lub wyłącza możliwość wprowadzania danych. Nie ma standardowego środowiska użytkownika do radzenia sobie z odmową dostępu i istnieje wiele możliwych opcji. W przykładowej aplikacji stan jest ustawiany na HeartRateModel pojedynczym obiekcie, który z kolei zgłasza odpowiednie zdarzenia.

Model, Widok i Kontroler

Aby przejrzeć HeartRateModel pojedynczy obiekt, otwórz HeartRateModel.cs plik:

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()));
                                                }
                                        });
                                });
                        }
                }
        }
}

Pierwsza sekcja to standardowy kod do tworzenia zdarzeń ogólnych i procedur obsługi. Początkowa część HeartRateModel klasy jest również standardowy do tworzenia obiektu pojedynczego pojedynczego wątku.

HeartRateModel Następnie uwidacznia 3 zdarzenia:

  • EnabledChanged — Wskazuje, że magazyn tętna został włączony lub wyłączony (należy pamiętać, że magazyn jest początkowo wyłączony).
  • ErrorMessageChanged — W przypadku tej przykładowej aplikacji mamy bardzo prosty model obsługi błędów: ciąg z ostatnim błędem .
  • HeartRateStored — Podniesione, gdy tętno jest przechowywane w bazie danych zestawu Health Kit.

Należy pamiętać, że za każdym razem, gdy te zdarzenia zostaną wyzwolone, odbywa się za pośrednictwem NSObject.InvokeOnMainThread()metody , co umożliwia subskrybentom aktualizowanie interfejsu użytkownika. Alternatywnie zdarzenia mogą być udokumentowane jako wywoływane w wątkach w tle, a odpowiedzialność za zapewnienie zgodności może zostać pozostawiona ich procedurom obsługi. Zagadnienia dotyczące wątków są ważne w aplikacjach zestawu kondycji, ponieważ wiele funkcji, takich jak żądanie uprawnień, jest asynchronicznych i wykonuje wywołania zwrotne w wątkach innych niż główne.

Kod specyficzny dla zestawu Heath w pliku HeartRateModel znajduje się w dwóch funkcjach HeartRateInBeatsPerMinute() i StoreHeartRate().

HeartRateInBeatsPerMinute() Konwertuje jego argument na silnie typizowane zestaw Health Kit HKQuantity. Typ ilości jest określony przez HKQuantityTypeIdentifierKey.HeartRate i jednostki ilości są HKUnit.Count dzielone przez HKUnit.Minute (innymi słowy, jednostka jest bije na minutę).

Funkcja StoreHeartRate() przyjmuje element HKQuantity (w przykładowej aplikacji utworzoną przez HeartRateInBeatsPerMinute() element ). Aby zweryfikować swoje dane, używa HKQuantity.IsCompatible() metody , która zwraca true , jeśli jednostki obiektu można przekonwertować na jednostki w argumencie . Jeśli ilość została utworzona za pomocą HeartRateInBeatsPerMinute() tej funkcji, oczywiście zwróci truewartość , ale zwróci true również, gdyby ilość została utworzona, na przykład Beats Per Hour. Częściej można HKQuantity.IsCompatible() użyć do weryfikowania masy, odległości i energii, które użytkownik lub urządzenie może wprowadzić lub wyświetlić w jednym systemie pomiaru (takim jak jednostki cesarskie), ale które mogą być przechowywane w innym systemie (np. jednostkach metryk).

Po zweryfikowaniu HKQuantitySample.FromType() zgodności ilości metoda fabryki służy do tworzenia silnie typizowanego heartRateSample obiektu. HKSample obiekty mają datę początkową i końcową; w przypadku błyskawicznych odczytów te wartości powinny być takie same, jak w przykładzie. Przykład nie ustawia również żadnych danych klucz-wartość w argumencie HKMetadata , ale można użyć kodu, takiego jak następujący kod, aby określić lokalizację czujnika:

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

Po utworzeniu heartRateSample elementu kod tworzy nowe połączenie z bazą danych z blokiem using. W tym bloku HKHealthStore.SaveObject() metoda podejmuje próbę asynchronicznego zapisu w bazie danych. Wynikowe wywołanie wyrażenia lambda wyzwala odpowiednie zdarzenia lub HeartRateStored ErrorMessageChanged.

Teraz, gdy model został zaprogramowany, nadszedł czas, aby zobaczyć, jak kontroler odzwierciedla stan modelu. Otwórz plik HKWorkViewController.cs. Konstruktor po prostu podłącza HeartRateModel jedenton do metod obsługi zdarzeń (ponownie można to zrobić w tekście za pomocą wyrażeń lambda, ale oddzielne metody sprawiają, że intencja jest nieco bardziej oczywista):

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

Oto odpowiednie programy obsługi:

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);
}

Oczywiście w aplikacji z jednym kontrolerem można uniknąć tworzenia oddzielnego obiektu modelu i używania zdarzeń przepływu sterowania, ale użycie obiektów modelu jest bardziej odpowiednie dla rzeczywistych aplikacji.

Uruchamianie przykładowej aplikacji

Symulator systemu iOS nie obsługuje zestawu Health Kit. Debugowanie musi odbywać się na urządzeniu fizycznym z systemem iOS 8.

Dołącz prawidłowo aprowidowane urządzenie deweloperskie z systemem iOS 8 do systemu. Wybierz go jako element docelowy wdrożenia w Visual Studio dla komputerów Mac, a następnie z menu wybierz pozycję Uruchom > debugowanie.

Ważne

W tym momencie pojawią się błędy związane z aprowizowaniem. Aby rozwiązać problemy z błędami, zapoznaj się z sekcją Tworzenie i aprowizowanie aplikacji zestawu kondycji powyżej. Składniki to:

  • Centrum deweloperów systemu iOS — jawny identyfikator aplikacji i zestaw kondycji z włączonym profilem aprowizacji.
  • Opcje projektu — identyfikator pakietu (jawny identyfikator aplikacji) i profil aprowizacji.
  • Kod źródłowy — Entitlements.plist & Info.plist

Zakładając, że aprowidowano prawidłowo ustawione, aplikacja zostanie uruchomiona. Gdy osiągnie ona metodę OnActivated , zażąda autoryzacji zestawu Health Kit. Przy pierwszym napotkaniu tego problemu przez system operacyjny użytkownik zostanie wyświetlony w następującym oknie dialogowym:

Użytkownik zostanie wyświetlony przy użyciu tego okna dialogowego

Włącz aplikację, aby zaktualizować dane tętna, a aplikacja pojawi się ponownie. Wywołanie ReactToHealthCarePermissions zwrotne zostanie aktywowane asynchronicznie. Spowoduje to zmianę HeartRateModel’s Enabled właściwości, co spowoduje wystąpienie EnabledChanged zdarzenia, co spowoduje HKPermissionsViewController.OnEnabledChanged() uruchomienie programu obsługi zdarzeń, co spowoduje włączenie StoreData przycisku. Na poniższym diagramie przedstawiono sekwencję:

Ten diagram przedstawia sekwencję zdarzeń

Naciśnij przycisk Nagraj. StoreData_TouchUpInside() Spowoduje to uruchomienie procedury obsługi, która podejmie próbę przeanalizowanenia wartości pola tekstowegoheartRate, przekonwertowania na HKQuantity wartość za pośrednictwem wcześniej omówionej HeartRateModel.HeartRateInBeatsPerMinute() funkcji i przekaże tę ilość do HeartRateModel.StoreHeartRate(). Jak wspomniano wcześniej, spowoduje to próbę HeartRateStored zapisania danych i wywoła zdarzenie lub ErrorMessageChanged .

Kliknij dwukrotnie przycisk Narzędzia główne na urządzeniu i otwórz aplikację Kondycja. Kliknij kartę Źródła i zostanie wyświetlona przykładowa aplikacja. Wybierz je i nie zezwalaj na aktualizowanie danych tętna. Kliknij dwukrotnie przycisk Narzędzia główne i wróć do aplikacji. Po raz kolejny ReactToHealthCarePermissions() zostanie wywołana, ale tym razem, ponieważ dostęp zostanie odrzucony, przycisk StoreData stanie się wyłączony (należy pamiętać, że występuje to asynchronicznie, a zmiana interfejsu użytkownika może być widoczna dla użytkownika końcowego).

Tematy zaawansowane

Odczytywanie danych z bazy danych zestawu Health Kit jest bardzo podobne do zapisywania danych: określa typy danych, do których próbuje się uzyskać dostęp, żąda autoryzacji, a jeśli ta autoryzacja zostanie udzielona, dane są dostępne z automatyczną konwersją na zgodne jednostki miary.

Istnieje wiele bardziej zaawansowanych funkcji zapytań, które umożliwiają wykonywanie zapytań opartych na predykacie i zapytaniach, które wykonują aktualizacje po zaktualizowaniu odpowiednich danych.

Deweloperzy aplikacji zestawu Health Kit powinni zapoznać się z sekcją Health Kit w wytycznych dotyczących przeglądu aplikacji firmy Apple.

Po zrozumieniu modeli zabezpieczeń i typów przechowywanie i odczytywanie danych w udostępnionej bazie danych zestawu Health Kit jest dość proste. Wiele funkcji w zestawie Health Kit działa asynchronicznie, a deweloperzy aplikacji muszą odpowiednio pisać swoje programy.

Na piśmie tego artykułu nie ma obecnie odpowiednika zestawu Health Kit w systemie Android lub Windows Phone.

Podsumowanie

W tym artykule pokazano, jak zestaw Health Kit umożliwia aplikacjom przechowywanie, pobieranie i udostępnianie informacji związanych z kondycją, a także udostępnianie standardowej aplikacji health, która umożliwia użytkownikowi dostęp do tych danych i kontrolę nad nimi.

Widzieliśmy również, jak prywatność, zabezpieczenia i integralność danych zastępują obawy dotyczące informacji i aplikacji związanych z kondycją oraz aplikacji korzystających z zestawu Health Kit muszą zajmować się wzrostem złożoności aspektów zarządzania aplikacjami (aprowizowanie), kodowanie (system typów zestawu Health Kit) i środowisko użytkownika (kontrola użytkowników za pośrednictwem okien dialogowych systemu i aplikacji kondycji).

Na koniec przyjrzeliśmy się prostej implementacji zestawu Health Kit przy użyciu dołączonej przykładowej aplikacji, która zapisuje dane pulsu w magazynie zestawu Health Kit i ma projekt asynchroniczny.