sensorkit

安装量: 442
排名: #5001

安装

npx skills add https://github.com/dpearson2699/swift-ios-skills --skill sensorkit

SensorKit Collect research-grade sensor data from iOS and watchOS devices for approved research studies. SensorKit provides access to ambient light, motion, device usage, keyboard metrics, visits, phone/messaging usage, speech metrics, face metrics, wrist temperature, heart rate, ECG, and PPG data. Targets Swift 6.3 / iOS 26+. SensorKit is restricted to Apple-approved research studies. Apps must submit a research proposal to Apple and receive the com.apple.developer.sensorkit.reader.allow entitlement before any sensor data is accessible. This is not a general-purpose sensor API -- use CoreMotion for standard accelerometer/gyroscope needs. Contents Overview and Requirements Entitlements Info.plist Configuration Authorization Available Sensors SRSensorReader Recording and Fetching Data SRDevice Common Mistakes Review Checklist References Overview and Requirements SensorKit enables research apps to record and fetch sensor data across iPhone and Apple Watch. The framework requires: Apple-approved research study -- submit a proposal at researchandcare.org . SensorKit entitlement -- Apple grants com.apple.developer.sensorkit.reader.allow only for approved studies. Manual provisioning profile -- Xcode requires an explicit App ID with the SensorKit capability enabled. User authorization -- the system presents a Research Sensor & Usage Data sheet that users approve per-sensor. 24-hour data hold -- newly recorded data is inaccessible for 24 hours, giving users time to delete data they do not want to share. An app can access up to 7 days of prior recorded data for an active sensor. Entitlements Add the SensorKit reader entitlement to a .entitlements file. List only the sensors your study uses: < key

com.apple.developer.sensorkit.reader.allow </ key

< array

< string

ambient-light-sensor </ string

< string

motion-accelerometer </ string

< string

motion-rotation-rate </ string

< string

device-usage </ string

< string

keyboard-metrics </ string

< string

messages-usage </ string

< string

phone-usage </ string

< string

visits </ string

< string

pedometer </ string

< string

on-wrist </ string

</ array

Xcode build settings for manual signing: Setting Value Code Signing Entitlements YourApp.entitlements Code Signing Identity Apple Developer Code Signing Style Manual Provisioning Profile Explicit profile with SensorKit capability Info.plist Configuration Three keys are required:

< key

NSSensorKitUsageDescription </ key

< string

This study monitors activity patterns for sleep research. </ string

< key

NSSensorKitPrivacyPolicyURL </ key

< string

https://example.com/privacy-policy </ string

< key

NSSensorKitUsageDetail </ key

< dict

< key

SRSensorUsageMotion </ key

< dict

< key

Description </ key

< string

Measures physical activity levels during the study. </ string

< key

Required </ key

< true /> </ dict

< key

SRSensorUsageAmbientLightSensor </ key

< dict

< key

Description </ key

< string

Records ambient light to assess sleep environment. </ string

</ dict

</ dict

If Required is true and the user denies that sensor, the system warns them that the study needs it and offers a chance to reconsider. Authorization Request authorization for the sensors your study needs. The system shows the Research Sensor & Usage Data sheet on first request. import SensorKit let reader = SRSensorReader ( sensor : . ambientLightSensor ) // Request authorization for multiple sensors at once SRSensorReader . requestAuthorization ( sensors : [ . ambientLightSensor , . accelerometer , . keyboardMetrics ] ) { error in if let error { print ( "Authorization request failed: ( error ) " ) } } Check a reader's current status before recording: switch reader . authorizationStatus { case . authorized : reader . startRecording ( ) case . denied : // User declined -- direct to Settings > Privacy > Research Sensor & Usage Data break case . notDetermined : // Request authorization first break @unknown default : break } Monitor status changes through the delegate: func sensorReader ( _ reader : SRSensorReader , didChange authorizationStatus : SRAuthorizationStatus ) { switch authorizationStatus { case . authorized : reader . startRecording ( ) case . denied : reader . stopRecording ( ) default : break } } Available Sensors Device Sensors Sensor Type Sample Type .deviceUsageReport Device usage SRDeviceUsageReport .keyboardMetrics Keyboard activity SRKeyboardMetrics .onWristState Watch wrist state SRWristDetection App Activity Sensors Sensor Type Sample Type .messagesUsageReport Messages app usage SRMessagesUsageReport .phoneUsageReport Phone call usage SRPhoneUsageReport User Activity Sensors Sensor Type Sample Type .accelerometer Acceleration data CMAccelerometerData .rotationRate Rotation rate CMGyroData .pedometerData Step/distance data CMPedometerData .visits Visited locations SRVisit .mediaEvents Media interactions SRMediaEvent .faceMetrics Face expressions SRFaceMetrics .heartRate Heart rate Heart rate data .odometer Speed/slope Odometer data .siriSpeechMetrics Siri speech SRSpeechMetrics .telephonySpeechMetrics Phone speech SRSpeechMetrics .wristTemperature Wrist temp (sleep) SRWristTemperatureSession .photoplethysmogram PPG stream SRPhotoplethysmogramSample .electrocardiogram ECG stream SRElectrocardiogramSample Environment Sensors Sensor Type Sample Type .ambientLightSensor Ambient light SRAmbientLightSample .ambientPressure Pressure/temp Pressure data SRSensorReader SRSensorReader is the central class for accessing sensor data. Each instance reads from a single sensor. import SensorKit // Create a reader for one sensor let lightReader = SRSensorReader ( sensor : . ambientLightSensor ) let keyboardReader = SRSensorReader ( sensor : . keyboardMetrics ) // Assign delegate to receive callbacks lightReader . delegate = self keyboardReader . delegate = self The reader communicates entirely through SRSensorReaderDelegate : Delegate Method Purpose sensorReader(:didChange:) Authorization status changed sensorReaderWillStartRecording(:) Recording is about to start sensorReader(:startRecordingFailedWithError:) Recording failed to start sensorReaderDidStopRecording(:) Recording stopped sensorReader(:didFetch:) Devices fetched sensorReader(:fetching:didFetchResult:) Sample received sensorReader(:didCompleteFetch:) Fetch completed sensorReader(:fetching:failedWithError:) Fetch failed Recording and Fetching Data Start and Stop Recording // Begin recording -- sensor stays active as long as any app has a stake reader . startRecording ( ) // Stop recording -- framework deactivates the sensor when // no app or system process is using it reader . stopRecording ( ) Fetch Data Build an SRFetchRequest with a time range and target device, then pass it to the reader: let request = SRFetchRequest ( ) request . device = SRDevice . current request . from = SRAbsoluteTime ( CFAbsoluteTimeGetCurrent ( ) - 86400 * 2 ) // 2 days ago request . to = SRAbsoluteTime . current ( ) reader . fetch ( request ) Receive results through the delegate: func sensorReader ( _ reader : SRSensorReader , fetching request : SRFetchRequest , didFetchResult result : SRFetchResult < AnyObject

) -> Bool { let timestamp = result . timestamp switch reader . sensor { case . ambientLightSensor : if let sample = result . sample as ? SRAmbientLightSample { let lux = sample . lux let chromaticity = sample . chromaticity let placement = sample . placement processSample ( lux : lux , chromaticity : chromaticity , at : timestamp ) } case . keyboardMetrics : if let sample = result . sample as ? SRKeyboardMetrics { let words = sample . totalWords let speed = sample . typingSpeed processKeyboard ( words : words , speed : speed , at : timestamp ) } case . deviceUsageReport : if let sample = result . sample as ? SRDeviceUsageReport { let wakes = sample . totalScreenWakes let unlocks = sample . totalUnlocks processUsage ( wakes : wakes , unlocks : unlocks , at : timestamp ) } default : break } return true // Return true to continue receiving results } func sensorReader ( _ reader : SRSensorReader , didCompleteFetch request : SRFetchRequest ) { print ( "Fetch complete for ( reader . sensor ) " ) } func sensorReader ( _ reader : SRSensorReader , fetching request : SRFetchRequest , failedWithError error : any Error ) { print ( "Fetch failed: ( error ) " ) } Data Holding Period SensorKit imposes a 24-hour holding period on newly recorded data. Fetch requests whose time range overlaps this period return no results. Design data collection workflows around this delay. SRDevice SRDevice identifies the hardware source for sensor samples. Use it to distinguish data from iPhone versus Apple Watch. // Get the current device let currentDevice = SRDevice . current print ( "Model: ( currentDevice . model ) " ) print ( "System: ( currentDevice . systemName ) ( currentDevice . systemVersion ) " ) // Fetch all available devices for a sensor reader . fetchDevices ( ) Handle fetched devices through the delegate: func sensorReader ( _ reader : SRSensorReader , didFetch devices : [ SRDevice ] ) { for device in devices { let request = SRFetchRequest ( ) request . device = device request . from = SRAbsoluteTime ( CFAbsoluteTimeGetCurrent ( ) - 86400 ) request . to = SRAbsoluteTime . current ( ) reader . fetch ( request ) } } func sensorReader ( _ reader : SRSensorReader , fetchDevicesDidFailWithError error : any Error ) { print ( "Failed to fetch devices: ( error ) " ) } SRDevice Properties Property Type Description model String User-defined device name name String Framework-defined device name systemName String OS name (iOS, watchOS) systemVersion String OS version productType String Hardware identifier current SRDevice Class property for the running device Common Mistakes DON'T: Attempt to use SensorKit without the entitlement // WRONG -- fails at runtime with SRError.invalidEntitlement let reader = SRSensorReader ( sensor : . ambientLightSensor ) reader . startRecording ( ) // CORRECT -- obtain entitlement from Apple first, configure manual // provisioning profile, then use SensorKit DON'T: Expect immediate data access // WRONG -- fetching data recorded moments ago returns nothing reader . startRecording ( ) // ... record for a few minutes ... let request = SRFetchRequest ( ) request . from = SRAbsoluteTime ( CFAbsoluteTimeGetCurrent ( ) - 300 ) request . to = SRAbsoluteTime . current ( ) reader . fetch ( request ) // Empty results due to 24-hour hold // CORRECT -- fetch data that is at least 24 hours old request . from = SRAbsoluteTime ( CFAbsoluteTimeGetCurrent ( ) - 86400 * 3 ) request . to = SRAbsoluteTime ( CFAbsoluteTimeGetCurrent ( ) - 86400 ) reader . fetch ( request ) DON'T: Forget to set the delegate before fetching // WRONG -- no delegate means no callbacks, results are silently lost let reader = SRSensorReader ( sensor : . accelerometer ) reader . startRecording ( ) reader . fetch ( request ) // CORRECT -- assign delegate first reader . delegate = self reader . startRecording ( ) reader . fetch ( request ) DON'T: Skip per-sensor Info.plist usage detail // WRONG -- missing NSSensorKitUsageDetail for the sensor // Authorization sheet shows no explanation, user is less likely to approve // CORRECT -- add usage detail for every sensor you request // See Info.plist Configuration section above DON'T: Ignore SRError codes // WRONG -- generic error handling func sensorReader ( _ reader : SRSensorReader , fetching : SRFetchRequest , failedWithError error : any Error ) { print ( "Error" ) } // CORRECT -- handle specific error codes func sensorReader ( _ reader : SRSensorReader , fetching : SRFetchRequest , failedWithError error : any Error ) { if let srError = error as ? SRError { switch srError . code { case . invalidEntitlement : // Entitlement missing or sensor not in entitlement array break case . noAuthorization : // User has not authorized this sensor break case . dataInaccessible : // Data in 24-hour holding period or otherwise unavailable break case . fetchRequestInvalid : // Invalid time range or device break case . promptDeclined : // User declined the authorization prompt break @unknown default : break } } } Review Checklist Apple-approved research study in place before development com.apple.developer.sensorkit.reader.allow entitlement lists only needed sensors Manual provisioning profile with explicit App ID and SensorKit capability NSSensorKitUsageDescription in Info.plist with clear study purpose NSSensorKitPrivacyPolicyURL in Info.plist with valid privacy policy URL NSSensorKitUsageDetail entries for every requested sensor Required key set appropriately for essential vs. optional sensors Authorization requested before recording, status checked before fetching Delegate assigned before calling startRecording() or fetch(:) Fetch request time ranges account for 24-hour data holding period SRError codes handled in all failure delegate methods fetchDevices() used to discover available devices before fetching stopRecording() called when data collection is complete sensorReader(:fetching:didFetchResult:) returns true to continue or false to stop References Extended patterns (delegate wiring, multi-sensor manager, sample type details): references/sensorkit-patterns.md SensorKit framework SRSensorReader SRSensor SRDevice SRFetchRequest Configuring your project for sensor reading com.apple.developer.sensorkit.reader.allow

返回排行榜