本文由CocoaChina翻译组成员 唧唧歪歪(
微博) 翻译自苹果官方文档:
The HealthKit Framework
HealthKit框架提供了一个结构,应用可以使用它来分享健康和健身数据。HealthKit管理从不同来源获得的数据,并根据用户的偏好设置,自动将不同来源的所有数据合并起来。应用还可以获取每个来源的原始数据,然后执行自己的数据合并。
HealthKit也可以直接与健康和健身设备一起工作。在iOS8.0中,系统可以自动将兼容的低功耗蓝牙心率仪的数据直接保存在HealthKit存储中。如果有M7运动协处理器,系统还可以自动导入计步数据。其他的设备和数据源必须要有配套的应用才可以获取数据并保存在HealthKit中。
HealthKit另外提供了一个应用来帮助管理用户的健康数据。健康应用为用户展示HealthKit的数据。用户可以使用健康应用来查看、添加、删除或者管理其全部的健康和健身数据。用户还可以编辑每种数据类型的分享权限。
HealthKit和健康应用在iPad上都不可用。HealthKit框架不能用于应用扩展。
HealthKit和隐私
由于健康数据可能是敏感的,HealthKit通过精确控制哪些信息允许应用读取,从而让用户可以控制这些数据。用户必须明确设置每个应用在HealthKit存储中读写的权限。用户可以单独为每种数据类型设置准许或拒绝的权限。例如,用户可以允许你的应用读取计步数据,但是不允许读取血糖水平。为了防止可能的信息泄露,应用是不知道它是否被禁止读取数据的。从应用的角度来看,如果被禁止读取数据,就是没有那种类型的数据存在。
HealthKit的数据不会保存在iCloud中,也不会在多设备间同步。这些数据只会保存在用户的本地设备中。为了安全考虑,当设备没有解锁时,HealthKit存储的数据是加密的。
另外,你的应用如果主要不是提供健康或健身服务的话,那就不能调用HealthKit的API。如果你的应用提供健康和健身服务,就必须要在销售文本和用户界面上明确的表明。特别是下面几条指导适用于所有HealthKit应用。
1. 你的应用不应该将HealthKit收集的数据用于广告或类似的服务。注意,可能在使用HealthKit框架应用中还是要服务广告,但是你不能使用HealthKit中的数据来服务广告。
2. 在没有用户的明确允许下,你不能向第三方展示任何HealthKit收集的数据。即使用户允许,你也只能向提供健康或健身服务的第三方展示这些数据。
3. 你不能将HealthKit收集的数据出售给广告平台、数据代理人或者信息经销商。
4. 如果用户允许,你可以将HealthKit数据共享给第三方用于医学研究。
5. 你必须明确说明,你和你的应用会怎样使用用户的HealthKit数据。
你必须为每个使用HealthKit框架的应用提供一份隐私策略。你可以在以下网站找到创建隐私策略的指导:
1. Personal Health Record model (for non-HIPAA apps):
http://www.healthit.gov/policy-researchers-implementers/personal-health-record-phr-model-privacy-notice
2. HIPAA model (for HIPAA covered apps):
http://www.hhs.gov/ocr/privacy/hipaa/modelnotices.html
这些模板由ONC开发,通过直白的语言和平易近人的设计来解释用户数据是如何被收集和共享的,从而提高用户的体验和理解。这些不是用来替代基本的互联网隐私策略,而且开发者应该咨询ONC来了解你的应用适用哪种模板。这些模板仅供参考,Apple不承担你使用这些模板带来的后果。
注意:
这一节提供了一些指导来帮助你创建一个HealthKit应用,并尊重用户的隐私。了解Apple对使用HealthKit和用户健康相关数据的要求是很有必要的。参看App Store Review Guidelines中的HealthKit章节来了解更多,可以在Apple的
App Review Support
页面中找到。
关于使用敏感用户数据的更多技术信息,参见
App Programming Guide for iOS 中的
Best Practices for Maintaining User Privacy 。
从接入HealthKit中获益
健康和健身应用可以从接入HealthKit中获益颇多。下面列出了一些主要的好处。
分离数据收集、数据处理和社交化。现代的健康和健身体验设计许多不同的方面,例如收集和分析数据,为用户提供可操作的信息和有用的可视化信息,以及允许用户参与到社区讨论中。现在由HealthKit负责实现这些方面,而你可以专注于实现你最感兴趣的方面,把其他的任务交给更专业的应用。
这些责任的分离也可以让用户受益。每个用户都可以随意选择最喜爱的体重追踪应用、计步应用和健康挑战应用。这意味着用户可以选择一套应用,每个应用都能很好的满足用户的某个需求。但是由于这些应用可以自由地交换数据,所以这一整套应用比单个应用能提供更好的体验。
例如,一些朋友决定参加一个日常的计步挑战。每个人都可以使用他偏爱的硬件设备或应用来追踪计步数据,但是他们都还可以使用相同的社交应用来挑战。
减少应用间分享的障碍。HealthKit使应用间共享数据变得更容易。对于开发者来说,你不在需要下载API并编写代码来和其他应用共享。当有新的HealthKit应用时,它们就通过HealthKit自动开始共享数据了。
由于不需要手动设置应用关联或者导入导出他们的数据,这对用户来说很好。用户仍然需要设置哪些应用可以读写HealthKit中的数据,还有每个应用可以读取到哪些数据。一旦用户允许访问,应用就可以自由无阻地读取数据了。
提供更丰富的数据和更有意义的内容。应用可以读取到范围更广的数据,从而可以得到一个完整的关于用户健康和健身需求。在许多情况下,应用可以基于HealthKit中的额外信息修改它的计量单位或者提示。例如,训练应用不仅可以根据用户已经消耗的热量,还可以参考他今天已经吃的食物种类和数量,来给出一个训练后吃什么的建议。
让应用参与到一个更大的生态系统中。应用通过共享它使用HealthKit收集的数据来获益。成为这个大生态系统的一部分能帮助提高你的应用的曝光度和实用性。更重要的是,接入HealthKit能让你的应用和用户已经拥有喜爱的应用一起工作。如果你的应用不能和其他已经在使用的应用共享数据,那么用户很可能就去寻找别的应用了。
HealthKit的设计思路
HealthKit是用来在应用间以一种有意义的方式共享数据。为了达到这点,框架限制只能使用预先定义好的数据类型和单位。这些限制保证了其他应用能理解这些数据是什么意思已经怎样使用。因此,开发者不能创建自定义数据类型和单位。而HealthKit尽量会提供一个应该完整的数据类型和单位。
框架还大量使用了子类化,在相似的类间创建层级关系。通常这些类间都有一些细微但是重要的差别。还有不少很相关的类,需要正确地区别开才能一起工作。例如
HKObject
和
HKObjectType
抽象类有很多平行层级的子类。当使用object和object type时,必须确保使用匹配的子类。
HealthKit中所有的对象都是HKObject的子类。大部分
HKObject 对象子类都是不可变的。每个对象都有下列属性:
1. UUID。每个对象的唯一标示符。
2. Source。数据的来源。来源可以是直接把数据存进HealthKit的设备,或者是应用。当一个对象保存进HealthKit中时,HealthKit会自动设置其来源。只有从HealthKit中获取的数据source属性才可用。
3. Metadata。一个包含关于该对象额外信息的字典。元数据包含预定义和自定义的键。预定义的键用来帮助在应用间共享数据。自定义的键用来扩展HealthKit对象类型,为对象添加针对应用的数据。
HealthKit对象主要分为2类:特征和样本。特征对象代表一些基本不变的数据。包括用户的生日、血型和生理性别。你的应用不能保存特征数据。用户必须通过健康应用来输入或者修改这些数据。
样本对象代表某个特定时间的数据。所有的样本对象都是
HKSample的子类。它们都有下列属性:
1. Type。样本类型。例如,这可能包括一个睡眠分析样本、一个身高样本或者一个计步样本。
2. Start date。样本的开始时间。
3. End date。样本的结束时间。如果样本代表时间中的某一刻,结束时间和开始时间相同。如果样本代表一段时间内收集的数据,结束时间应该晚于开始时间。
样本可以细分为四个样本类型。
1. 类别样本。这种样本代表一些可以被分为有限种类的数据。在iOS8.0中,只有一种类别样本,睡眠分析。更多信息,参见
HKCategorySample Class Reference。
2. 数量样本。这种样本代表一些可以存储为数值的数据。数量样本是HealthKit中最常见的数据类型。这些包括用户的身高和体重,还有一些其他数据,例如行走的步数,用户的体温和脉搏率。更多信息,参见
HKQuantitySample Class Reference。
3. Correlation。这种样本代表复合数据,包含一个或多个样本。在iOS8.0中,HealthKit使用correlation来代表食物和血压。在创建书屋或者血压数据时,你应该使用correlation。更多信息,参见
HKCorrelation Class Reference。
4. Workout。Workout代表某些物理活动,像跑步、游泳,甚至游戏。Workout通常有类型、时长、距离、和消耗能量这些属性。你还可以为一个workout关联许多详细的样本。不像correlation,这些样本是不包含在workout里的。但是,它们可以通过workout获取到。更多信息,参见
HKWorkout Class Reference。
设置HealthKit
在你开始使用HealthKit之前,必须要执行下列步骤:
1. 在Xcode中打开HealthKit功能。
2. 调用
isHealthDataAvailable 方法来查看HealthKit在该设备上是否可用。HealthKit在iPad上不可用。
3. 为你的应用实例化一个
HKHealthStore 对象。每个应用只需要一个HealthKit存储实例。这个存储实例就是你和HealthKit数据库交互的主要接口。
4. 使用
requestAuthorizationToShareTypes:readTypes:completion:
方法来请求获取HealthKit数据的权限。对每种类型的数据,你都必须请求许可来共享和读取。
如果用户允许分享某种类型的数据,那么你可以创建这种类型的新样本,并保存在HealthKit中。你应该使用
authorizationStatusForType:来检查是否允许分享这种类型的数据。
如果用户允许读取某种类型的数据,那么你就可以从HealthKit中读取这些数据。不幸的是,即使知道用户拒绝读取某种类型的数据,也可能会显示出潜在的健康问题。因此,你的应用无法确定用户是否允许读取数据。如果你没有得到读取某种数据的许可,那简单来看就好像是HealthKit中没有这种类型的数据。
关于设置HealthKit的更多内容,参见
HKHealthStore Class Reference。
有一个展示了如何设置和使用HealthKit的例子,参见
Fit: Store and Retrieve HealthKit Data。
向HealthKit 存储中添加样本
你的应用可以创建新的样本,并添加到HealthKit存储中。对所有样本类型来说,大致的过程都是类似的,但是又有一些不同。
1. 在
HealthKit Constants Reference 中找到正确的类型标识符。
3. 使用对象类型,创建一个匹配的
HKSample 子类。
4. 使用
saveObject:withCompletion:
方法将对象保存到HealthKit 存储中。
每个
HKSample 子类都有自己的便捷方法来实例化样本对象。流程如下图所示。
对于数量样本,你必须创建一个
HKQuantity 类的实例。数量的单位必须和类型标识符文档中描述的可用单位相关。例如,
HKQuantityTypeIdentifierHeight 文档中说明它使用长度单位,因此,你的数量必须使用厘米、米、英尺、英寸或者其他长度单位。更多信息,参见
HKQuantitySample Class Reference。
对于类别样本,它的值必须和类型标识符文档中描述的枚举值相关。例如,
HKCategoryTypeIdentifierSleepAnalysis 文档中说明它使用
HKCategoryValueSleepAnalysis 枚举值。因此你在创建样本时必须从这个枚举中传递一个值。更多信息,参见
HKCategorySample Class Reference。
对于correlation,你必须先创建correlation包含的所有样本。correlation的类型标识符描述了它可以包含的类型和对象的数量。不要把被包含的对象存进HealthKit。它们是以correlation的一部分存储的。更多信息,参见
HKCorrelation Class Reference。
workout和其他类型的样本有些不同。首先,创建
HKWorkoutType 实例并不需要指定类型标识符。所有的workout都是用同样的类型标识符。第二,对于每个workout你都需要提供一个
HKWorkoutActivityType 值。这个值定义了workout中执行的活动的类型。最后,当workout保存到HealthKit后,你可以给workout关联额外的样本。这些样本提供了workout的详细信息。更多信息,参见
HKWorkout Class Reference。
读取HealthKit数据
HealthKit提供了许多方法来读取数据。
1. 直接方法调用。HealthKit提供了直接读取特征数据的方法。这些方法只能用于读取特征数据。更多信息,参见
HKHealthStore Class Reference。
2. 样本查询。这是使用最多的查询。使用样本查询来读取任何类型的样本数据。当你想要对结果进行排序或者限制返回的样本总数时,样本查询就特别有用。更多信息,参见
HKSampleQuery Class Reference。
3. 观察者查询。这是一个长时间运行的查询,它会检测HealthKit存储,并在匹配到的样本发生变化时通知你。如果当存储发生变化时你想得到通知,就使用观察者查询。你可以让这些查询在后台执行。更多信息,参见
HKObserverQuery Class Reference。
4. 锚定对象查询。用这种查询来搜索添加进存储的项。当锚定查询第一次执行时,会返回存储中所有匹配的样本。在接下来的执行中,只会返回上一次执行之后添加的项目。通常,锚定对象查询会和观察者查询一起使用。观察者查询告诉你某些项目发生了变化,而锚定对象查询来决定有哪些(如果有的话)项目被添加进了存储。更多信息,参见
HKAnchoredObjectQuery Class Reference。
5. 统计查询。使用这种查询来在一系列匹配的样本中执行统计运算。你可以使用统计查询来计算样本的总和、最小值、最大值或平均值。更多信息,参见
HKStatisticsQuery Class Reference。
6. 统计集合查询。使用这种查询来在一系列长度固定的时间间隔中执行多次统计查询。通常使用这种查询来生成图表。查询提供了一些简单的方法来计算某些值,例如,每天消耗的总热量或者每5分钟行走的步数。统计集合查询是长时间运行的。查询可以返回当前的统计集合,也可以监测HealthKit存储,并对更新做出响应。更多信息,参见
HKStatisticsCollectionQuery Class Reference。
7. Correlation查询。使用这种查询来在correlation查找数据。这种查询可以为correlation中每个样本类型包含独立的谓词。如果你只是想匹配correlation类型,那么请使用样本查询。更多信息,参见
HKCorrelation Class Reference。
8. 来源查询。使用这种查询来查找HealthKit存储中的匹配数据的来源(应用和设备)。来源查询会列出储存的特定样本类型的所有来源。更多信息,参见
HKSourceQuery Class Reference。
单位换算
HealthKit使用
HKUnit 和
HKQuantity 类来支持单位。
HKUnit 提供了单一单位的表示。它支持大部分的公制和英制单位,当然还包括基本单位和符合单位。基本单位代表单一的度量,例如米、磅或者秒。复合单位使用数学运算连接一个或多个基本单位,例如m/s或者lb/ft2。
HKUnit 提供了便捷方法来创建HealthKit支持的所有基本单位。它还提供了构建复合单位需要的数学运算。最后,你还可以通过直接使用恰当的格式化的单位字符串来创建复合单位。
更多信息,参见
HKUnit Class Reference。
HKQuantity 类存储了给定单位的值。之后你可以用任何兼容的单位来取值。这样,你的应用就可以很轻松的完成单位换算。
更多信息,参见
HKQuantity Class Reference。
在某些场合,你可以使用格式化器来本地化数量。iOS8提供了提供了新的格式化器来处理长度(NSLengthFormatter)、质量(NSMassFormatter)和能量(NSEnergyFormatter)。对于其他的数量,你需要自己来换算单位和本地化数据。
多线程
HealthKit存储是线程安全的,大部分HealthKit对象是不可变的。通常来说,你可以在多线程环境中安全地使用HealthKit。
注意:
所有HealthKit API的完成回调都在一个私有的后台队列中执行。所以在你更新用户界面或者修改一些只能在主线程中处理的资源之前,你应该把这些数据传回主线程。
关于多线程和并发编程的更多信息,参见
Concurrency Programming Guide。
添加数字签名
HealthKit中的数字签名元数据对象提供了由可信设备生成的样本记录的数据完整性。元数据项存储了一份数字签名过的样本记录副本。签名是由设备生成的(由于设备存储了私有签名密钥,所以设备应该是防篡改的)。这样数据的使用者就可以通过设备的公钥来检查签名,进而验证记录数据是否被修改过。由于每条记录都是独立签名的,所以每条记录总共能存储大约1K bytes的签名。因此,这种元数据签名项是给那些样本率最多在每天几次的记录使用的。更高的样本率需要对样本组进行签名,这已经超出了本文档的范围。
通常,私钥是在制造时置入防篡改的测量设备中的。(私钥重置或证书更新的政策或机制不在本文档的范围内)相关的公钥会由设备制造商公布,例如在它们的网站上。设备应该将每个样本的样本数据和签名传给iOS应用,这两者都会储存在HealthKit数据库中。注意,数字签名的公私钥是用来提供数据完整性检查的,不是用来加密的。数据记录中的实际值都是明文。
数字签名的格式是IETF RFC 5652中的CMS(Cryptographic Message Syntax)。签名使用ASN.1的DER(Distinguished Encoding Rules)编码。使用的信息摘要应该是SHA256,签名加密应该是FIPS PUB 186-4 Digital Signature Standard Elliptic Curve P-256。这样长度和效率都有保证。另外,整个签名都应该使用bsae64编码,这样就能存储在HealthKit NSString 元数据对象中。
签名应该是ASN.1 Signed-data Content Type:
SignedData ::= SEQUENCE { version CMSVersion, digestAlgorithms DigestAlgorithmIdentifiers, encapContentInfo EncasulatedContentInfo, signerInfos SignerInfo }
SignerInfo Type是:
SignerInfo ::= SEQUENCE { version CMSVersion, sid SignerIdentifier, digestAlgorithm DigestAlgorithmIdentifier, signatureAlgorithem SignatureAlgorithmIdentifier, signatureSignatureValue }
上面就是摘要和签名的算法。可选项目都没有包含在其中。SignerIdentifier用来取得适当的公钥,来对签名进行验证。
EncapsulatedContentInfo是从由设备生成的样本记录中的相关项目的副本。副本应该用ASN.1 DER编码,并应至少包含一个样本时间戳和采样值。将记录数据拷贝进签名内,是为了有一个稳定的定义良好的二进制编码(ASN.1 DER),这对于生成一个可验证的签名来说是必要的。ASN.1编码的plist结构(键值对),应该能满足大部分记录类型。(参见“使用ASN.1 DER来编码plist结构”)
转载自:http://www.cocoachina.com/ios/20140915/9624.html