|  | // Copyright 2017 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #import "SensorsPlugin.h" | 
|  | #import <CoreMotion/CoreMotion.h> | 
|  |  | 
|  | @implementation FLTSensorsPlugin | 
|  |  | 
|  | + (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar { | 
|  | FLTAccelerometerStreamHandler* accelerometerStreamHandler = | 
|  | [[FLTAccelerometerStreamHandler alloc] init]; | 
|  | FlutterEventChannel* accelerometerChannel = | 
|  | [FlutterEventChannel eventChannelWithName:@"plugins.flutter.io/accelerometer" | 
|  | binaryMessenger:[registrar messenger]]; | 
|  | [accelerometerChannel setStreamHandler:accelerometerStreamHandler]; | 
|  |  | 
|  | FLTGyroscopeStreamHandler* gyroscopeStreamHandler = [[FLTGyroscopeStreamHandler alloc] init]; | 
|  | FlutterEventChannel* gyroscopeChannel = | 
|  | [FlutterEventChannel eventChannelWithName:@"plugins.flutter.io/gyroscope" | 
|  | binaryMessenger:[registrar messenger]]; | 
|  | [gyroscopeChannel setStreamHandler:gyroscopeStreamHandler]; | 
|  | } | 
|  |  | 
|  | @end | 
|  |  | 
|  | const double GRAVITY = 9.8; | 
|  | CMMotionManager* _motionManager; | 
|  |  | 
|  | void _initMotionManager() { | 
|  | if (!_motionManager) { | 
|  | _motionManager = [[CMMotionManager alloc] init]; | 
|  | } | 
|  | } | 
|  |  | 
|  | static void sendTriplet(Float64 x, Float64 y, Float64 z, FlutterEventSink sink) { | 
|  | NSMutableData* event = [NSMutableData dataWithCapacity:3 * sizeof(Float64)]; | 
|  | [event appendBytes:&x length:sizeof(Float64)]; | 
|  | [event appendBytes:&y length:sizeof(Float64)]; | 
|  | [event appendBytes:&z length:sizeof(Float64)]; | 
|  | sink([FlutterStandardTypedData typedDataWithFloat64:event]); | 
|  | } | 
|  |  | 
|  | @implementation FLTAccelerometerStreamHandler | 
|  |  | 
|  | - (FlutterError*)onListenWithArguments:(id)arguments eventSink:(FlutterEventSink)eventSink { | 
|  | _initMotionManager(); | 
|  | [_motionManager | 
|  | startAccelerometerUpdatesToQueue:[[NSOperationQueue alloc] init] | 
|  | withHandler:^(CMAccelerometerData* accelerometerData, NSError* error) { | 
|  | CMAcceleration acceleration = accelerometerData.acceleration; | 
|  | // Multiply by gravity, and adjust sign values to | 
|  | // align with Android. | 
|  | sendTriplet(-acceleration.x * GRAVITY, -acceleration.y * GRAVITY, | 
|  | -acceleration.z * GRAVITY, eventSink); | 
|  | }]; | 
|  | return nil; | 
|  | } | 
|  |  | 
|  | - (FlutterError*)onCancelWithArguments:(id)arguments { | 
|  | [_motionManager stopAccelerometerUpdates]; | 
|  | return nil; | 
|  | } | 
|  |  | 
|  | @end | 
|  |  | 
|  | @implementation FLTGyroscopeStreamHandler | 
|  |  | 
|  | - (FlutterError*)onListenWithArguments:(id)arguments eventSink:(FlutterEventSink)eventSink { | 
|  | _initMotionManager(); | 
|  | [_motionManager | 
|  | startGyroUpdatesToQueue:[[NSOperationQueue alloc] init] | 
|  | withHandler:^(CMGyroData* gyroData, NSError* error) { | 
|  | CMRotationRate rotationRate = gyroData.rotationRate; | 
|  | sendTriplet(rotationRate.x, rotationRate.y, rotationRate.z, eventSink); | 
|  | }]; | 
|  | return nil; | 
|  | } | 
|  |  | 
|  | - (FlutterError*)onCancelWithArguments:(id)arguments { | 
|  | [_motionManager stopGyroUpdates]; | 
|  | return nil; | 
|  | } | 
|  |  | 
|  | @end |