Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/sensors/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.4.1+3

* Improve documentation and add unit test coverage.

## 0.4.1+2

* Remove AndroidX warnings.
Expand Down
34 changes: 30 additions & 4 deletions packages/sensors/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,22 @@ A Flutter plugin to access the accelerometer and gyroscope sensors.

## Usage

To use this plugin, add `sensors` as a [dependency in your pubspec.yaml file](https://flutter.io/platform-plugins/).
To use this plugin, add `sensors` as a [dependency in your pubspec.yaml
file](https://flutter.io/platform-plugins/).

This will expose three classes of sensor events, through three different
streams.

- `AccelerometerEvent`s describe the velocity of the device, including the
effects of gravity. Put simply, you can use accelerometer readings to tell if
the device is moving in a particular direction.
- `UserAccelerometerEvent`s also describe the velocity of the device, but don't
include gravity. They can also be thought of as just the user's affect on the
device.
- `GyroscopeEvent`s describe the rotation of the device.

Each of these is exposed through a `BroadcastStream`: `accelerometerEvents`,
`userAccelerometerEvents`, and `gyroscopeEvents`, respectively.


### Example
Expand All @@ -14,10 +29,21 @@ To use this plugin, add `sensors` as a [dependency in your pubspec.yaml file](ht
import 'package:sensors/sensors.dart';

accelerometerEvents.listen((AccelerometerEvent event) {
// Do something with the event.
print(event);
});
// [AccelerometerEvent (x: 0.0, y: 9.8, z: 0.0)]

userAccelerometerEvents.listen((AccelerometerEvent event) {
print(event);
});
// [UserAccelerometerEvent (x: 0.0, y: 0.0, z: 0.0)]

gyroscopeEvents.listen((GyroscopeEvent event) {
// Do something with the event.
print(event);
});
```
// [GyroscopeEvent (x: 0.0, y: 0.0, z: 0.0)]

```

Also see the `example` subdirectory for an example application that uses the
sensor data.
11 changes: 11 additions & 0 deletions packages/sensors/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# This exists to add a lint for missing API docs just on this specific package,
# since not all packages have coverage for all their public members yet and
# adding it in would be non-trivial. `public_member_api_docs` should be applied
# to new packages going forward, and ideally the main `analysis_options.yaml`
# file as soon as possible.

include: ../../analysis_options.yaml

linter:
rules:
- public_member_api_docs
2 changes: 2 additions & 0 deletions packages/sensors/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// ignore_for_file: public_member_api_docs

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:sensors/sensors.dart';
Expand Down
2 changes: 2 additions & 0 deletions packages/sensors/example/lib/snake.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// ignore_for_file: public_member_api_docs

import 'dart:async';
import 'dart:math' as math;

Expand Down
47 changes: 47 additions & 0 deletions packages/sensors/lib/sensors.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,48 +14,95 @@ const EventChannel _userAccelerometerEventChannel =
const EventChannel _gyroscopeEventChannel =
EventChannel('plugins.flutter.io/sensors/gyroscope');

/// Discrete reading from an accelerometer. Accelerometers measure the velocity
/// of the device. Note that these readings include the effects of gravity. Put
/// simply, you can use accelerometer readings to tell if the device is moving in
/// a particular direction.
class AccelerometerEvent {
/// Contructs an instance with the given [x], [y], and [z] values.
AccelerometerEvent(this.x, this.y, this.z);

/// Acceleration force along the x axis (including gravity) measured in m/s^2.
///
/// When the device is held upright facing the user, positive values mean the
/// device is moving to the right and negative mean it is moving to the left.
final double x;

/// Acceleration force along the y axis (including gravity) measured in m/s^2.
///
/// When the device is held upright facing the user, positive values mean the
/// device is moving towards the sky and negative mean it is moving towards
/// the ground.
final double y;

/// Acceleration force along the z axis (including gravity) measured in m/s^2.
///
/// This uses a right-handed coordinate system. So when the device is held
/// upright and facing the user, positive values mean the device is moving
/// towards the user and negative mean it is moving away from them.
final double z;

@override
String toString() => '[AccelerometerEvent (x: $x, y: $y, z: $z)]';
}

/// Discrete reading from a gyroscope. Gyroscopes measure the rate or rotation of
/// the device in 3D space.
class GyroscopeEvent {
/// Contructs an instance with the given [x], [y], and [z] values.
GyroscopeEvent(this.x, this.y, this.z);

/// Rate of rotation around the x axis measured in rad/s.
///
/// When the device is held upright, this can also be thought of as describing
/// "pitch". The top of the device will tilt towards or away from the
/// user as this value changes.
final double x;

/// Rate of rotation around the y axis measured in rad/s.
///
/// When the device is held upright, this can also be thought of as describing
/// "yaw". The lengthwise edge of the device will rotate towards or away from
/// the user as this value changes.
final double y;

/// Rate of rotation around the z axis measured in rad/s.
///
/// When the device is held upright, this can also be thought of as describing
/// "roll". When this changes the face of the device should remain facing
/// forward, but the orientation will change from portrait to landscape and so
/// on.
final double z;

@override
String toString() => '[GyroscopeEvent (x: $x, y: $y, z: $z)]';
}

/// Like [AccelerometerEvent], this is a discrete reading from an accelerometer
/// and measures the velocity of the device. However, unlike
/// [AccelerometerEvent], this event does not include the effects of gravity.
class UserAccelerometerEvent {
/// Contructs an instance with the given [x], [y], and [z] values.
UserAccelerometerEvent(this.x, this.y, this.z);

/// Acceleration force along the x axis (excluding gravity) measured in m/s^2.
///
/// When the device is held upright facing the user, positive values mean the
/// device is moving to the right and negative mean it is moving to the left.
final double x;

/// Acceleration force along the y axis (excluding gravity) measured in m/s^2.
///
/// When the device is held upright facing the user, positive values mean the
/// device is moving towards the sky and negative mean it is moving towards
/// the ground.
final double y;

/// Acceleration force along the z axis (excluding gravity) measured in m/s^2.
///
/// This uses a right-handed coordinate system. So when the device is held
/// upright and facing the user, positive values mean the device is moving
/// towards the user and negative mean it is moving away from them.
final double z;

@override
Expand Down
3 changes: 2 additions & 1 deletion packages/sensors/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ description: Flutter plugin for accessing the Android and iOS accelerometer and
gyroscope sensors.
author: Flutter Team <[email protected]>
homepage: https://github.com/flutter/plugins/tree/master/packages/sensors
version: 0.4.1+2
version: 0.4.1+3

flutter:
plugin:
Expand All @@ -20,6 +20,7 @@ dev_dependencies:
flutter_test:
sdk: flutter
e2e: ^0.2.0
mockito: ^4.1.1

environment:
sdk: ">=2.0.0-dev.28.0 <3.0.0"
Expand Down
90 changes: 56 additions & 34 deletions packages/sensors/test/sensors_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';
import 'dart:typed_data';

import 'package:flutter/services.dart';
Expand All @@ -16,44 +15,67 @@ void main() {
test('$accelerometerEvents are streamed', () async {
const String channelName = 'plugins.flutter.io/sensors/accelerometer';
const List<double> sensorData = <double>[1.0, 2.0, 3.0];
_initializeFakeSensorChannel(channelName, sensorData);

const StandardMethodCodec standardMethod = StandardMethodCodec();

void emitEvent(ByteData event) {
// TODO(hterkelsen): Remove this when defaultBinaryMessages is in stable.
// https://github.com/flutter/flutter/issues/33446
// ignore: deprecated_member_use
BinaryMessages.handlePlatformMessage(
channelName,
event,
(ByteData reply) {},
);
}
final AccelerometerEvent event = await accelerometerEvents.first;

expect(event.x, sensorData[0]);
expect(event.y, sensorData[1]);
expect(event.z, sensorData[2]);
});

test('$gyroscopeEvents are streamed', () async {
const String channelName = 'plugins.flutter.io/sensors/gyroscope';
const List<double> sensorData = <double>[3.0, 4.0, 5.0];
_initializeFakeSensorChannel(channelName, sensorData);

final GyroscopeEvent event = await gyroscopeEvents.first;

expect(event.x, sensorData[0]);
expect(event.y, sensorData[1]);
expect(event.z, sensorData[2]);
});

test('$userAccelerometerEvents are streamed', () async {
const String channelName = 'plugins.flutter.io/sensors/user_accel';
const List<double> sensorData = <double>[6.0, 7.0, 8.0];
_initializeFakeSensorChannel(channelName, sensorData);

bool isCanceled = false;
final UserAccelerometerEvent event = await userAccelerometerEvents.first;

expect(event.x, sensorData[0]);
expect(event.y, sensorData[1]);
expect(event.z, sensorData[2]);
});
}

void _initializeFakeSensorChannel(String channelName, List<double> sensorData) {
const StandardMethodCodec standardMethod = StandardMethodCodec();

void _emitEvent(ByteData event) {
// TODO(hterkelsen): Remove this when defaultBinaryMessages is in stable.
// https://github.com/flutter/flutter/issues/33446
// ignore: deprecated_member_use
BinaryMessages.setMockMessageHandler(channelName, (ByteData message) async {
final MethodCall methodCall = standardMethod.decodeMethodCall(message);
if (methodCall.method == 'listen') {
emitEvent(standardMethod.encodeSuccessEnvelope(sensorData));
emitEvent(null);
return standardMethod.encodeSuccessEnvelope(null);
} else if (methodCall.method == 'cancel') {
isCanceled = true;
return standardMethod.encodeSuccessEnvelope(null);
} else {
fail('Expected listen or cancel');
}
});

final AccelerometerEvent event = await accelerometerEvents.first;
expect(event.x, 1.0);
expect(event.y, 2.0);
expect(event.z, 3.0);
BinaryMessages.handlePlatformMessage(
channelName,
event,
(ByteData reply) {},
);
}

await Future<void>.delayed(Duration.zero);
expect(isCanceled, isTrue);
// TODO(hterkelsen): Remove this when defaultBinaryMessages is in stable.
// https://github.com/flutter/flutter/issues/33446
// ignore: deprecated_member_use
BinaryMessages.setMockMessageHandler(channelName, (ByteData message) async {
final MethodCall methodCall = standardMethod.decodeMethodCall(message);
if (methodCall.method == 'listen') {
_emitEvent(standardMethod.encodeSuccessEnvelope(sensorData));
_emitEvent(null);
return standardMethod.encodeSuccessEnvelope(null);
} else if (methodCall.method == 'cancel') {
return standardMethod.encodeSuccessEnvelope(null);
} else {
fail('Expected listen or cancel');
}
});
}