Xamarin.iOS의 HealthKit

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

건강 관련 데이터는 매우 민감하고 중요하기 때문에 Health Kit는 측정 단위와 기록되는 정보 유형(예: 혈당 수준 또는 심박수)과의 명시적 연관성으로 강력하게 형식화됩니다. 또한 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 디바이스입니다.

Important

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

Health Kit 앱 만들기 및 프로비전

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

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

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

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

명시적 앱 ID 및 프로비전 프로필

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

현재 앱 ID는 개발자 센터 인증서, 식별자 및 프로필 섹션에 나열됩니다. 종종 이 목록에는 앱 ID 이름이 임의의 수의 *접미사와 함께 사용될 수 있음을 나타내는 ID - 값이 표시됩니다. 이러한 Wild카드 앱 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에서 솔루션을 만들어야 합니다. Health Kit 액세스는 모든 iOS C# 또는 F# 프로젝트에서 사용할 수 있습니다.

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

Enter the explicit App ID

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

Select the Provisioning Profile

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

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

Entitlements.plist 및 Info.plist 값

샘플 앱에는 모든 프로젝트 템플릿에 포함되지 않은 파일(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문을 확인합니다.

다음 코드는 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;
        }
}

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

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

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

Important

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

앱이 데이터에 액세스할 수 있는지 여부를 확인하기 위해 이 앱 HKHealthStore.GetAuthorizationStatus() 이 사용되고 전달됩니다 HKQuantityTypeIdentifierKey.HeartRate. 반환된 상태 따라 앱은 데이터를 입력하는 기능을 사용하거나 사용하지 않도록 설정합니다. 액세스 거부를 처리하기 위한 표준 사용자 환경이 없으며 가능한 많은 옵션이 있습니다. 예제 앱에서 상태 차례로 관련 이벤트를 발생시키는 싱글톤 개체에 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()됩니다. 또는 이벤트가 백그라운드 스레드에서 발생하는 것으로 문서화될 수 있으며 호환성을 처리기에 맡기도록 해야 합니다. 권한 요청과 같은 많은 함수가 비동기적이며 비 기본 스레드에서 콜백을 실행하기 때문에 Health Kit 애플리케이션에서 스레드 고려 사항이 중요합니다.

히스 키트 관련 코드 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() 데이터베이스에 비동기 쓰기를 시도합니다. 람다 식에 대한 결과 호출은 관련 이벤트를 HeartRateStoredErrorMessageChanged트리거합니다.

이제 모델이 프로그래밍되었으므로 컨트롤러가 모델의 상태를 어떻게 반영하는지 확인할 차례입니다. 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 배포 대상으로 선택하고 메뉴에서 디버그 실행을 > 선택합니다.

Important

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

  • iOS 개발자 센터 - 명시적 앱 ID 및 상태 키트를 사용하도록 설정된 프로비저닝 프로필입니다.
  • 프로젝트 옵션 - 번들 식별자(명시적 앱 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(). 앞에서 설명한 대로 데이터를 저장하려고 시도하고 이벤트 HeartRateStored 또는 ErrorMessageChanged 이벤트를 발생합니다.

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

고급 주제

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

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

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

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

이 문서를 작성할 때 현재 Android 또는 Windows 전화 Health Kit에 해당하는 항목이 없습니다.

요약

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

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

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