学术科研
在已获 Apple 批准的研究 App 中配置并采集…
适用于已获 Apple 批准的研究 App,需要在 iPhone/Apple Watch 上配置 SensorKit entitlement、授权并采集研究级传感器数据。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
在已获 Apple 批准的研究 App 特定
解决思路
- 选择精确的 `SRSensor`,并逐个核对该传感器的可用性。
- 普通运动/活动功能改用 `CoreMotion`;健康记录和锻炼数据改用 `HealthKit`。
- 在 `researchandcare.org` 提交研究提案,先获得 Apple 批准的研究项目。
- 获取 SensorKit entitlement `com.apple.developer.sensorkit.reader.allow`,该权限仅授予获批研究。
- 使用手动描述文件:在 Xcode 中配置显式 App ID 并启用 SensorKit capability。
- 按传感器处理用户授权:系统会显示 Research Sensor & Usage Data 表单,用户逐传感器批准。
- 围绕 Data Holding Period 设计抓取时机;活动传感器最多可访问之前 7 天已记录数据。
- 将 SensorKit reader entitlement 添加到 `.entitlements` 文件。
- 在 entitlement 数组中只列出 Apple 为研究批准的传感器。
- 在 entitlement 数组中填入类似 `ambient-light-sensor`、`motion-accelerometer`、`device-usage`、`keyboard-metrics` 的字符串,并只保留获批项。
- 选择每个获批传感器的确切 entitlement 字符串和 `NSSensorKitUsageDetail` key 时,加载 Entitlement and Usage-Detail Catalog(`references/sensorkit-patterns.md#entitlement-and-usage-detail-catalog`);对专用传感器逐一核对各自的 `SRSensor` 页面。
- 手动签名时设置 Code Signing Entitlements 为 entitlements 文件,Code Signing Identity 为 `Apple Developer`,Code Signing Style 为 `Manual`,Provisioning Profile 为带 SensorKit capability 的显式描述文件。
- 在 Info.plist 中添加 `NSSensorKitUsageDescription`,填写研究会话中向用户展示的研究目的。
- 在 Info.plist 中添加 `NSSensorKitPrivacyPolicyURL`,链接到研究的隐私政策。
- 在 Info.plist 中添加 `NSSensorKitUsageDetail`,为每个请求的传感器提供逐传感器用途说明。
- 对每个请求的传感器使用精确的 usage-detail dictionary;除 motion 和 ambient-light 示例外,加载 catalog 做传感器映射。
- 在 `NSSensorKitUsageDetail` 中为必要传感器设置 `Required` 为 `true`;若用户拒绝,系统会警告研究需要该传感器并允许重新考虑。
- 请求研究所需传感器的授权;首次请求时系统显示 Research Sensor & Usage Data 表单。
- 使用 `SRSensorReader.requestAuthorization(sensors:completion:)` 一次请求多个传感器,例如 `[.ambientLightSensor, .accelerometer, .keyboardMetrics]`。
- 用同一个状态处理方法处理初始授权检查和 delegate 中的授权状态变更。
- 根据 `SRAuthorizationStatus` 操作:`authorized` 时调用 `reader.startRecording()`;`denied` 时调用 `reader.stopRecording()` 并指引用户到 `Settings > Privacy > Research Sensor & Usage Data`;`notDetermined` 时先请求授权;`@unknown default` 时保留处理。
- 加载 Sensor Catalog(`references/sensorkit-patterns.md#sensor-catalog`)将每个 `SRSensor` 映射到其 sample type。
- 只请求研究获批的传感器;重新核对所选传感器的可用性和 usage-detail key。
- 使用 `SRSensorReader` 作为访问传感器数据的核心类;每个实例只读取一个传感器。
- 为每个传感器创建 `SRSensorReader` 实例,并给每个实例设置 delegate。
- 通过 `SRSensorReaderDelegate` 接收授权、录制、设备抓取和样本抓取生命周期回调;加载 Delegate Method Catalog(`references/sensorkit-patterns.md#delegate-method-catalog`)获取完整接线。
- 开始录制时调用 `reader.startRecording()`;只要任一 App 或系统进程仍在使用,传感器保持活动。
- 停止录制时调用 `reader.stopRecording()`;当无 App 或系统进程使用时,框架停用传感器。
- 抓取数据时构建 `SRFetchRequest`,设置 `device`、`from`、`to` 时间范围,然后传给 `reader.fetch(request)`。
- 在 delegate 的 `sensorReader(_:fetching:didFetchResult:)` 中处理结果:读取 `result.timestamp`,按 `reader.sensor` 将 `result.sample` 转为对应类型(如 `SRAmbientLightSample`、`SRKeyboardMetrics`、`SRDeviceUsageReport`),处理样本后返回 `true` 继续接收结果;返回 `false` 可停止。
- 在 `sensorReader(_:fetching:didFetchResult:)` 中处理 ambient light 样本时读取 `sample.lux`、`sample.chromaticity`、`sample.placement`。
- 在 `sensorReader(_:fetching:didFetchResult:)` 中处理 keyboard metrics 时读取 `sample.totalWords`、`sample.typingSpeed`。
- 在 `sensorReader(_:fetching:didFetchResult:)` 中处理 device usage report 时读取 `sample.totalScreenWakes`、`sample.totalUnlocks`。
- 实现 `sensorReader(_:didCompleteFetch:)` 处理抓取完成。
- 实现 `sensorReader(_:fetching:failedWithError:)` 处理抓取失败。
- 注意某些流每个结果返回一个对象,而 recorded motion、ECG、PPG、ambient pressure 流可能返回 recorded samples 数组;需按类型转换处理。
- 处理 24 小时 Data Holding Period:新记录数据有 24 小时持有期,抓取时间范围与持有期重叠会返回空结果;不要误判为录制失败,需围绕该延迟设计采集工作流。
- 使用 `SRDevice` 标识传感器样本的硬件来源,区分 iPhone 与 Apple Watch。
- 通过 `SRDevice.current` 获取当前设备,并读取 `model`、`systemName`、`systemVersion` 等属性。
- 读取 `SRDevice` 属性:`model`、`name`、`systemName`、`systemVersion`、`productType` 以及类属性 `current`,用于识别设备。
- 调用 `reader.fetchDevices()` 发现可用设备。
- 实现 `sensorReader(_:didFetch:)`:遍历返回设备,为每个设备创建 `SRFetchRequest`,设置 `device`、`from`、`to`,然后 fetch。
- 实现 `sensorReader(_:fetchDevicesDidFailWithError:)` 处理设备抓取失败。
- 不要在没有 entitlement 时构造生产 reader;先获得 Apple 研究批准、传感器特定 entitlement 值和匹配的手动描述文件。
- 不要期望立即访问数据;应用 Data Holding Period,重叠持有期的空抓取不是录制失败。
- 不要在抓取前忘记设置 delegate;在 `startRecording()` 或 `fetch(_:)` 前设置 delegate,因为结果和失败通过 delegate 回调。
- 不要跳过每个传感器的 Info.plist usage detail;为每个请求传感器添加精确的 `NSSensorKitUsageDetail` 条目。
- 不要忽略 `SRError` 代码;至少区分 `.invalidEntitlement`、`.noAuthorization`、`.dataInaccessible`、`.fetchRequestInvalid`、`.promptDeclined` 和未知未来代码;加载 Full Delegate Implementation(`references/sensorkit-patterns.md#full-delegate-implementation`)获取完整 switch 和回调接线。
- 按 Review Checklist 验证:开发前已有 Apple 批准的研究项目。
- 按 Review Checklist 验证:`com.apple.developer.sensorkit.reader.allow` entitlement 只列出所需传感器。
- 按 Review Checklist 验证:手动描述文件带显式 App ID 和 SensorKit capability。
- 按 Review Checklist 验证:Info.plist 中的 `NSSensorKitUsageDescription` 清楚说明研究目的。
- 按 Review Checklist 验证:Info.plist 中的 `NSSensorKitPrivacyPolicyURL` 指向有效隐私政策 URL。
- 按 Review Checklist 验证:为每个请求传感器都配置了 `NSSensorKitUsageDetail` 条目。
- 按 Review Checklist 验证:为必要与可选传感器正确设置 `Required` key。
- 按 Review Checklist 验证:录制前请求授权,抓取前检查授权状态。
- 按 Review Checklist 验证:在调用 `startRecording()` 或 `fetch(_:)` 前已设置 delegate。
- 按 Review Checklist 验证:抓取请求时间范围考虑 24 小时 data holding period。
- 按 Review Checklist 验证:所有失败 delegate 方法中处理 `SRError` 代码。
- 按 Review Checklist 验证:抓取前使用 `fetchDevices()` 发现可用设备。
- 按 Review Checklist 验证:数据采集完成时调用 `stopRecording()`。
- 按 Review Checklist 验证:`sensorReader(_:fetching:didFetchResult:)` 返回 `true` 继续或 `false` 停止。
适用边界 · 注意事项
- 不要用 SensorKit 处理普通运动/活动功能;这类功能改用 CoreMotion。
- 不要用 SensorKit 处理健康记录或锻炼数据;这类数据改用 HealthKit。
- 没有 Apple 批准研究项目、SensorKit entitlement 或匹配的手动描述文件时不要使用 SensorKit。