Xamarin.iOS의 HealthKit

Health Kit는 사용자의 상태 관련 정보에 대한 보안 데이터 저장소를 제공합니다. Health Kit 앱은 사용자의 명시적 사용 권한으로 이 데이터 저장소에 읽고 쓰고 관련 데이터가 추가될 때 알림을 받을 수 있습니다. 앱은 데이터를 표시하거나 사용자가 Apple에서 제공한 상태 앱을 사용하여 모든 데이터의 대시보드를 볼 수 있습니다.

건강 관련 데이터는 매우 민감하고 중요하기 때문에 Health Kit는 측정 단위와 기록되는 정보 유형(예: 혈당 수준 또는 심박수)과 명시적인 연관성으로 강력하게 입력됩니다. 또한 Health Kit 앱은 명시적 자격을 사용해야 하고, 특정 유형의 정보에 대한 액세스를 요청해야 하며, 사용자는 앱에 이러한 유형의 데이터에 대한 액세스 권한을 명시적으로 부여해야 합니다.

이 문서에서는 다음을 소개합니다.

  • Health Kit 데이터베이스에 액세스하기 위한 애플리케이션 프로비저닝 및 사용자 권한 요청을 비롯한 Health Kit의 보안 요구 사항
  • 데이터를 잘못 적용하거나 잘못 해석할 가능성을 최소화하는 Health Kit의 형식 시스템
  • 시스템 차원의 공유 상태 키트 데이터 저장소에 쓰기

이 문서에서는 데이터베이스 쿼리, 측정 단위 간 변환 또는 새 데이터 알림 받기와 같은 고급 항목에 대해서는 다루지 않습니다.

이 문서에서는 사용자의 심박수를 기록하는 샘플 애플리케이션을 만듭니다.

A sample application to record the users heart rate

요구 사항

이 문서에 제시된 단계를 완료하려면 다음이 필요합니다.

  • Xcode 7 및 iOS 8 이상 – Apple의 최신 Xcode 및 iOS API를 설치하고 개발자의 컴퓨터에 구성해야 합니다.
  • Mac용 Visual Studio 또는 Visual Studio – 최신 버전의 Mac용 Visual Studio 개발자 컴퓨터에 설치하고 구성해야 합니다.
  • iOS 8 이상 디바이스 – 테스트를 위해 최신 버전의 iOS 8 이상을 실행하는 iOS 디바이스입니다.

중요

상태 키트는 iOS 8에서 도입되었습니다. 현재 iOS 시뮬레이터에서는 상태 키트를 사용할 수 없으며 디버깅을 수행하려면 실제 iOS 디바이스에 연결해야 합니다.

Health Kit 앱 만들기 및 프로비전

Xamarin iOS 8 애플리케이션에서 HealthKit API를 사용하려면 먼저 올바르게 구성하고 프로비전해야 합니다. 이 섹션에서는 Xamarin 애플리케이션을 올바르게 설정하는 데 필요한 단계를 설명합니다.

Health Kit 앱에는 다음이 필요합니다.

  • 명시적 앱 ID입니다.
  • 명시적 앱 IDHealth Kit 권한과 연결된 프로비전 프로필입니다.
  • Entitlements.plist 형식 Boolean 의 속성이 com.apple.developer.healthkit .로 설정된 경우 Yes
  • Info.plist 값이 UIRequiredDeviceCapabilities 있는 항목 Stringhealthkit이 포함된 키입니다.
  • 또한 앱이 Info.plist 데이터를 쓸 경우 키 NSHealthUpdateUsageDescription 에 대한 설명과 앱이 Health Kit 데이터를 읽으려는 경우 키 NSHealthShareUsageDescription 에 대한 설명과 String 같은 적절한 개인 정보 설명 항목 String 이 있어야 합니다.

iOS 앱 프로비전에 대한 자세한 내용을 알아보려면 Xamarin의 시작 시리즈의 Device Provisioning 문서에서 개발자 인증서, 앱 ID, 프로비저닝 프로필 및 앱 자격 간의 관계를 설명합니다.

명시적 앱 ID 및 프로비저닝 프로필

명시적 앱 ID 및 적절한 프로비저닝 프로필 만들기는 Apple의 iOS 개발자 센터 내에서 수행됩니다.

현재 앱 ID는 개발자 센터 인증서, 식별자 & 프로필 섹션에 나열됩니다. 이 목록에는 앱 ID이름을 여러 접미사와 함께 사용할 수 있음을 나타내는 ID - 값*이 표시되는 경우가 많습니다. 이러한 와일드카드 앱 ID는 Health Kit와 함께 사용할 수 없습니다.

명시적 앱 ID를 만들려면 오른쪽 위에 있는 단추를 클릭하여 +iOS 앱 ID 등록 페이지로 이동하세요.

Registering an app on the Apple Developer Portal

위의 이미지와 같이 앱 설명을 만든 후 명시적 앱 ID 섹션을 사용하여 애플리케이션에 대한 ID를 만듭니다. App Services 섹션의 서비스 사용 섹션에서 상태 키트를 확인합니다.

완료되면 계속 단추를 눌러 계정에 앱 ID 를 등록합니다. 인증서, 식별자 및 프로필 페이지로 돌아갑니다. 프로비전 프로필을 클릭하여 현재 프로비저닝 프로필 목록으로 이동하고 오른쪽 위 모서리에 있는 단추를 클릭하여 +iOS 프로비저닝 프로필 추가 페이지로 이동합니다. iOS 앱 개발 옵션을 선택하고 계속을 클릭하여 앱 ID 선택 페이지로 이동하세요. 여기서는 이전에 지정한 명시적 앱 ID 를 선택합니다.

Select the explicit App ID

계속을 클릭하고 나머지 화면에서 작업합니다. 여기서 개발자 인증서, 디바이스 및 이 프로비저닝 프로필이름을 지정합니다.

Generating the Provisioning Profile

생성을 클릭하고 프로필 만들기를 기다립니다. 파일을 다운로드하고 두 번 클릭하여 Xcode에 설치합니다. Xcode > 기본 설정 > 계정 보기 세부 정보 아래에서 설치 중인지 확인할 수 있습니다>... 방금 설치한 프로비저닝 프로필이 표시되어야 하며, 자격 행에 Health Kit 및 기타 특수 서비스에 대한 아이콘이 있어야 합니다.

Viewing the profile in Xcode

앱 ID 및 프로비저닝 프로필을 Xamarin.iOS 앱과 연결

설명된 대로 적절한 프로비저닝 프로필을 만들고 설치한 후에는 일반적으로 Mac용 Visual Studio 또는 Visual Studio 솔루션을 만들어야 합니다. 상태 키트 액세스는 모든 iOS C# 또는 F# 프로젝트에서 사용할 수 있습니다.

Xamarin iOS 8 프로젝트를 직접 만드는 과정을 안내하는 대신 이 문서에 첨부된 샘플 앱(미리 빌드된 Storyboard 및 코드 포함)을 엽니다. 샘플 앱을 Health Kit 지원 프로비저닝 프로필과 연결하려면 솔루션 패드에서 Project 마우스 오른쪽 단추로 클릭하고 옵션 대화 상자를 표시합니다. iOS 애플리케이션 패널로 전환하고 이전에 만든 명시적 앱 ID를 앱의 번들 식별자로 입력합니다.

Enter the explicit App ID

이제 iOS 번들 서명 패널로 전환합니다. 명시적 앱 ID와 연결된 최근에 설치된 프로비저닝 프로필은 이제 프로비저닝 프로필로 사용할 수 있습니다.

Select the Provisioning Profile

프로비전 프로필을 사용할 수 없는 경우 iOS 애플리케이션 패널에서 번들 식별자를 다시 확인하고 iOS 개발자 센터 지정된 것과 프로비전 프로필이 설치되어 있는지 확인합니다>(Xcode > 기본 설정 > 계정 보기 세부 정보...).

상태 키트 사용 프로비저닝 프로필을 선택하면 확인을 클릭하여 Project 옵션 대화 상자를 닫습니다.

Entitlements.plist 및 Info.plist 값

샘플 앱에는 모든 Project 템플릿에 포함되지 않은 파일(Health Kit 사용 앱에 필요)이 포함되어 Entitlements.plist 있습니다. 프로젝트에 자격이 없는 경우 프로젝트를 마우스 오른쪽 단추로 클릭하고 파일 > 새 파일... > iOS > Entitlements.plist 를 선택하여 수동으로 추가합니다.

궁극적으로 Entitlements.plist 다음과 같은 키와 값 쌍이 있어야 합니다.

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

마찬가지로 앱의 Info.plist 경우 키와 연결된 값 healthkitUIRequiredDeviceCapabilities 있어야 합니다.

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

이 문서와 함께 제공되는 샘플 애플리케이션에는 모든 필수 키가 포함된 미리 구성된 Entitlements.plist 키가 포함되어 있습니다.

프로그래밍 상태 키트

Health Kit 데이터 저장소는 앱 간에 공유되는 개인 사용자별 데이터 저장소입니다. 상태 정보가 매우 중요하기 때문에 사용자는 데이터 액세스를 허용하기 위해 긍정적인 단계를 수행해야 합니다. 이 액세스는 부분적일 수 있으며(쓰기는 하지만 읽지 않음, 일부 데이터 형식에 대한 액세스는 아니지만 다른 형식의 액세스 등) 언제든지 해지될 수 있습니다. Health Kit 애플리케이션은 방어적으로 작성해야 하며, 많은 사용자가 상태 관련 정보를 저장하는 것을 주저할 것이라는 점을 이해해야 합니다.

Health Kit 데이터는 Apple에서 지정한 형식으로 제한됩니다. 이러한 유형은 엄격하게 정의됩니다: 혈액 형과 같은 일부는 Apple 제공 열거형의 특정 값으로 제한되며 다른 유형은 크기와 측정 단위 (예 : 그램, 칼로리 및 리터)를 결합합니다. 호환되는 측정 단위를 공유하는 데이터도 해당 HKObjectType단위로 구분됩니다. 예를 들어 형식 시스템은 둘 다 측정 단위를 사용 HKUnit.Count 하더라도 값을 필드에 HKQuantityTypeIdentifier.FlightsClimbed 저장 HKQuantityTypeIdentifier.NumberOfTimesFallen 하려는 잘못된 시도를 포착합니다.

Health Kit 데이터 저장소에 저장 가능한 형식은 모두 .의 HKObjectType하위 클래스입니다. HKCharacteristicType 개체는 생물학적 성별, 혈액 유형 및 생년월일을 저장합니다. 하지만 더 일반적인 것은 HKSampleType 특정 시간 또는 일정 기간 동안 샘플링되는 데이터를 나타내는 개체입니다.

HKSampleType objects chart

HKSampleType 는 추상이며 4개의 구체적인 서브클래스를 가집니다. 현재는 절전 분석이라는 데이터 형식 HKCategoryType 이 하나만 있습니다. Health Kit의 대부분의 데이터는 친숙한 팩터리 디자인 패턴을 사용하여 만들어지는 개체의 형식 HKQuantityType 및 저장 HKQuantitySample 입니다.

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

HKQuantityType 형식 범위는 입니다 HKQuantityTypeIdentifier.ActiveEnergyBurnedHKQuantityTypeIdentifier.StepCount.

사용자에게 사용 권한 요청

최종 사용자는 앱이 Health Kit 데이터를 읽거나 쓸 수 있도록 긍정적인 단계를 수행해야 합니다. 이 작업은 iOS 8 디바이스에 미리 설치된 상태 앱을 통해 수행됩니다. Health Kit 앱을 처음 실행하면 사용자에게 시스템 제어 상태 액세스 대화 상자가 표시됩니다.

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

나중에 사용자는 상태 앱의 원본 대화 상자를 사용하여 사용 권한을 변경할 수 있습니다.

The user can change permissions using Health apps Sources dialog

상태 정보는 매우 민감하기 때문에 앱 개발자는 앱이 실행되는 동안 사용 권한이 거부되고 변경될 것이라는 기대와 함께 방어적으로 프로그램을 작성해야 합니다. 가장 일반적인 관용구는 메서드의 UIApplicationDelegate.OnActivated 사용 권한을 요청한 다음 사용자 인터페이스를 적절하게 수정하는 것입니다.

사용 권한 연습

Health Kit 프로비전 프로젝트에서 파일을 엽니다 AppDelegate.cs . 파일 맨 위에 있는 ;를 사용하여 HealthKit문을 확인합니다.

다음 코드는 상태 키트 사용 권한과 관련이 있습니다.

private HKHealthStore healthKitStore = new HKHealthStore ();

public override void OnActivated (UIApplication 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;
        }
}

이러한 메서드의 모든 코드는 인라인으로 OnActivated수행할 수 있지만 샘플 앱은 별도의 메서드를 사용하여 의도를 더 명확하게 만듭니다. ValidateAuthorization() 작성 중인 특정 형식에 대한 액세스를 요청하는 데 필요한 단계(앱이 원하는 경우 읽기)를 포함하며 ReactToHealthCarePermissions() 사용자가 Health.app 권한 대화 상자와 상호 작용한 후 활성화되는 콜백입니다.

ValidateAuthorization() 작업은 앱이 해당 데이터를 업데이트하기 위해 작성 및 권한 부여를 요청하는 집합 HKObjectTypes 을 빌드하는 것입니다. 샘플 앱 HKObjectType 에서 키 KHQuantityTypeIdentifierKey.HeartRate에 대한 것입니다. 집합이 비어 있는 동안 이 형식이 집합 typesToWritetypesToRead 에 추가됩니다. 이러한 집합 및 콜백에 ReactToHealthCarePermissions() 대한 참조가 에 전달됩니다 HKHealthStore.RequestAuthorizationToShare().

ReactToHealthCarePermissions() 사용자가 사용 권한 대화 상자와 상호 작용한 후 콜백이 호출되고 두 가지 정보가 booltrue 전달됩니다. 즉, 사용자가 사용 권한 대화 상자와 상호 작용한 경우 값이고 NSError null이 아닌 경우 사용 권한 대화 상자 표시와 관련된 일종의 오류를 나타냅니다.

중요

이 함수에 대한 인수를 명확히 하기 위해 성공오류 매개 변수는 사용자가 Health Kit 데이터에 액세스할 수 있는 권한을 부여했는지 여부를 나타내지 않습니다. 사용자에게 데이터에 대한 액세스를 허용할 수 있는 기회가 제공되었음을 나타냅니다.

앱이 데이터에 액세스할 수 있는지 여부를 확인하기 위해 이 앱 HKHealthStore.GetAuthorizationStatus() 이 사용되고 전달됩니다 HKQuantityTypeIdentifierKey.HeartRate. 반환된 상태에 따라 앱은 데이터를 입력하는 기능을 사용하거나 사용하지 않도록 설정합니다. 액세스 거부를 처리하기 위한 표준 사용자 환경이 없으며 가능한 많은 옵션이 있습니다. 예제 앱에서 상태는 Singleton 개체에 HeartRateModel 설정되며, 이로 인해 관련 이벤트가 발생합니다.

모델, 뷰 및 컨트롤러

싱글톤 개체를 HeartRateModel 검토하려면 파일을 엽니다.HeartRateModel.cs

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

첫 번째 섹션은 제네릭 이벤트 및 처리기를 만들기 위한 상용구 코드입니다. 클래스의 HeartRateModel 초기 부분은 스레드로부터 안전한 싱글톤 개체를 만들기 위한 상용구이기도 합니다.

그런 다음, HeartRateModel 3개의 이벤트를 노출합니다.

  • EnabledChanged - 심박수 스토리지를 사용하거나 사용하지 않도록 설정했음을 나타냅니다(스토리지는 처음에 사용하지 않도록 설정됨).
  • ErrorMessageChanged - 이 샘플 앱의 경우 매우 간단한 오류 처리 모델인 마지막 오류가 있는 문자열이 있습니다.
  • HeartRateStored - 심박수가 Health Kit 데이터베이스에 저장될 때 발생합니다.

이러한 이벤트가 발생할 때마다 구독자가 UI를 업데이트할 수 있는 이벤트를 통해 NSObject.InvokeOnMainThread()수행됩니다. 또는 이벤트가 백그라운드 스레드에서 발생하는 것으로 문서화될 수 있으며 호환성을 보장하는 책임이 처리기에 맡기도록 할 수 있습니다. 권한 요청과 같은 많은 함수가 비동기적이며 주 스레드가 아닌 스레드에서 콜백을 실행하기 때문에 상태 키트 애플리케이션에서 스레드 고려 사항이 중요합니다.

히스 키트 관련 코드 HeartRateModel 는 두 가지 함수 HeartRateInBeatsPerMinute()StoreHeartRate().

HeartRateInBeatsPerMinute() 는 인수를 강력한 형식의 Health Kit HKQuantity로 변환합니다. 수량의 유형은 수량 단위로 HKQuantityTypeIdentifierKey.HeartRate 지정되고 수량 단위는 HKUnit.Count당 비트 단위로 나뉩니다 HKUnit.Minute .

함수는 StoreHeartRate() (샘플 앱에서 만든 HeartRateInBeatsPerMinute() 앱)을 사용합니다 HKQuantity . 데이터의 유효성을 검사하기 위해 개체의 단위를 HKQuantity.IsCompatible() 인수의 단위로 변환할 수 있는지를 반환 true 하는 메서드를 사용합니다. 이 수량을 사용하여 HeartRateInBeatsPerMinute() 만든 경우 분명히 반환되지만 수량이 생성된 경우(예: 시간당 Beats)도 반환 truetrue 됩니다. 더 일반적으로 사용자 HKQuantity.IsCompatible() 또는 디바이스가 한 측정 시스템(예: 임페리얼 단위)에서 입력하거나 표시할 수 있지만 다른 시스템(예: 메트릭 단위)에 저장될 수 있는 질량, 거리 및 에너지의 유효성을 검사하는 데 사용할 수 있습니다.

수량의 호환성이 확인 HKQuantitySample.FromType() 되면 팩터리 메서드를 사용하여 강력한 형식의 개체를 만듭니다 heartRateSample . HKSample 개체에는 시작 날짜와 종료 날짜가 있습니다. 즉석 판독값의 경우 이러한 값은 예제와 동일해야 합니다. 또한 샘플은 인수에 HKMetadata 키-값 데이터를 설정하지 않지만 다음 코드와 같은 코드를 사용하여 센서 위치를 지정할 수 있습니다.

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

코드가 heartRateSample 만들어지면 using 블록을 사용하여 데이터베이스에 대한 새 연결을 만듭니다. 해당 블록 내에서 메서드는 HKHealthStore.SaveObject() 데이터베이스에 비동기 쓰기를 시도합니다. 람다 식에 대한 결과 호출은 관련 이벤트 중 하나 HeartRateStored 또는 ErrorMessageChanged.

이제 모델이 프로그래밍되었으므로 컨트롤러가 모델의 상태를 어떻게 반영하는지 확인할 차례입니다. HKWorkViewController.cs 파일을 엽니다. 생성자는 단순히 싱글톤을 이벤트 처리 메서드에 연결 HeartRateModel 합니다(다시 람다 식을 사용하여 인라인으로 수행할 수 있지만 별도의 메서드는 의도를 좀 더 분명하게 만듭니다.)

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

관련 처리기는 다음과 같습니다.

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

물론 단일 컨트롤러가 있는 애플리케이션에서는 별도의 모델 개체를 만들고 제어 흐름에 이벤트를 사용하지 않도록 방지할 수 있지만 모델 개체를 사용하는 것이 실제 앱에 더 적합합니다.

샘플 앱 실행

iOS 시뮬레이터는 Health Kit를 지원하지 않습니다. 디버깅은 iOS 8을 실행하는 물리적 디바이스에서 수행해야 합니다.

올바르게 프로비전된 iOS 8 개발 디바이스를 시스템에 연결합니다. Mac용 Visual Studio 배포 대상으로 선택하고 메뉴에서 디버그 실행을 >선택합니다.

중요

이 시점에서 프로비전과 관련된 실수가 나타납니다. 오류를 해결하려면 위의 Health Kit 앱 만들기 및 프로비전 섹션을 검토합니다. 구성 요소는 다음과 같습니다.

  • iOS 개발자 센터 - 명시적 앱 ID & Health Kit 지원 프로비저닝 프로필
  • Project 옵션 - 번들 식별자(명시적 앱 ID) & 프로비저닝 프로필.
  • 소스 코드 - Entitlements.plist & Info.plist

프로비전이 제대로 설정되었다고 가정하면 애플리케이션이 시작됩니다. 메서드 OnActivated 에 도달하면 Health Kit 권한 부여를 요청합니다. 운영 체제에서 이 문제를 처음 발견하면 사용자에게 다음 대화 상자가 표시됩니다.

The user will be presented with this dialog

앱을 사용하도록 설정하여 심박수 데이터를 업데이트하면 앱이 다시 나타납니다. 콜백은 ReactToHealthCarePermissions 비동기적으로 활성화됩니다. 이렇게 하면 속성이 HeartRateModel’sEnabled 변경되어 이벤트가 발생 EnabledChanged 하며, 이로 인해 HKPermissionsViewController.OnEnabledChanged() 이벤트 처리기가 실행되어 단추가 StoreData 활성화됩니다. 다음 다이어그램은 시퀀스를 보여줍니다.

This diagram shows the sequence of events

레코드 단추를 누릅니다. 이렇게 하면 StoreData_TouchUpInside() 처리기가 실행되어 텍스트 필드의 heartRate 값을 구문 분석하고, 앞에서 설명한 HeartRateModel.HeartRateInBeatsPerMinute() 함수를 HKQuantity 통해 변환하고, 해당 수량을 전달합니다HeartRateModel.StoreHeartRate(). 앞에서 설명한 대로 데이터를 저장하려고 시도하고 이벤트 또는 ErrorMessageChanged 이벤트를 HeartRateStored 발생합니다.

디바이스에서 단추를 두 번 클릭하고 상태 앱을 엽니다. 원본 탭 클릭하면 샘플 앱이 나열됩니다. 이를 선택하고 심박수 데이터를 업데이트할 수 있는 권한을 허용하지 않습니다. 단추를 두 번 클릭하고 앱으로 다시 전환합니다. 다시 ReactToHealthCarePermissions() 한 번 호출되지만 이번에는 액세스가 거부되므로 StoreData 단추가 비활성화됩니다(비동기적으로 발생하고 사용자 인터페이스의 변경 내용이 최종 사용자에게 표시될 수 있음).

고급 항목

Health Kit 데이터베이스에서 데이터를 읽는 것은 데이터 작성과 매우 유사합니다. 하나는 액세스하려는 데이터 형식을 지정하고, 권한 부여를 요청하며, 권한 부여가 부여되면 호환되는 측정 단위로 자동 변환하여 데이터를 사용할 수 있습니다.

관련 데이터가 업데이트되면 업데이트를 수행하는 조건자 기반 쿼리 및 쿼리를 허용하는 더 정교한 쿼리 함수가 많이 있습니다.

Health Kit 애플리케이션 개발자는 Apple 앱 검토 지침의 Health Kit 섹션을 검토해야 합니다.

보안 및 형식 시스템 모델이 이해되면 공유 Health Kit 데이터베이스에 데이터를 저장하고 읽는 것은 매우 간단합니다. Health Kit 내의 많은 함수는 비동기적으로 작동하며 애플리케이션 개발자는 프로그램을 적절하게 작성해야 합니다.

이 문서의 작성을 기준으로, 현재 안드로이드 또는 Windows Phone 상태 키트에 해당되지 않습니다.

요약

이 문서에서는 Health Kit를 통해 사용자가 이 데이터에 액세스하고 제어할 수 있는 표준 상태 앱을 제공하는 동시에 상태 관련 정보를 저장, 검색 및 공유할 수 있는 방법을 살펴보았습니다.

또한 개인 정보 보호, 보안 및 데이터 무결성이 상태 관련 정보에 대한 우려를 어떻게 재정의하고 있으며, Health Kit를 사용하는 앱은 애플리케이션 관리 측면(프로비저닝), 코딩(Health Kit의 유형 시스템) 및 사용자 환경(시스템 대화 및 상태 앱을 통한 사용 권한 사용자 제어)의 복잡성 증가를 처리해야 합니다.

마지막으로, Health Kit 저장소에 하트비트 데이터를 쓰고 비동기 인식 디자인을 사용하는 포함된 샘플 앱을 사용하여 Health Kit의 간단한 구현을 살펴보겠습니다.