[sensors] Documentation and test improvements (#2272)
- Add missing dartdoc coverage and expand on existing documentation.
- Add an analyzer warning for this package so that public doc coverage
doesn't regress.
- Improve unit test coverage.
- Expand on the existing README.
diff --git a/packages/sensors/CHANGELOG.md b/packages/sensors/CHANGELOG.md
index ea48858..aecf8d4 100644
--- a/packages/sensors/CHANGELOG.md
+++ b/packages/sensors/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.4.1+3
+
+* Improve documentation and add unit test coverage.
+
## 0.4.1+2
* Remove AndroidX warnings.
diff --git a/packages/sensors/README.md b/packages/sensors/README.md
index fdd4502..4bb9f4f 100644
--- a/packages/sensors/README.md
+++ b/packages/sensors/README.md
@@ -5,7 +5,22 @@
## 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
@@ -14,10 +29,21 @@
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);
});
-```
\ No newline at end of file
+// [GyroscopeEvent (x: 0.0, y: 0.0, z: 0.0)]
+
+```
+
+Also see the `example` subdirectory for an example application that uses the
+sensor data.
diff --git a/packages/sensors/analysis_options.yaml b/packages/sensors/analysis_options.yaml
new file mode 100644
index 0000000..4d3c53a
--- /dev/null
+++ b/packages/sensors/analysis_options.yaml
@@ -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
diff --git a/packages/sensors/example/lib/main.dart b/packages/sensors/example/lib/main.dart
index e574a64..575e049 100644
--- a/packages/sensors/example/lib/main.dart
+++ b/packages/sensors/example/lib/main.dart
@@ -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';
diff --git a/packages/sensors/example/lib/snake.dart b/packages/sensors/example/lib/snake.dart
index b870791..2b7cad4 100644
--- a/packages/sensors/example/lib/snake.dart
+++ b/packages/sensors/example/lib/snake.dart
@@ -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;
diff --git a/packages/sensors/lib/sensors.dart b/packages/sensors/lib/sensors.dart
index 7b41a49..0b6f1b5 100644
--- a/packages/sensors/lib/sensors.dart
+++ b/packages/sensors/lib/sensors.dart
@@ -14,48 +14,95 @@
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
diff --git a/packages/sensors/pubspec.yaml b/packages/sensors/pubspec.yaml
index 38e6982..b750d93 100644
--- a/packages/sensors/pubspec.yaml
+++ b/packages/sensors/pubspec.yaml
@@ -3,7 +3,7 @@
gyroscope sensors.
author: Flutter Team <flutter-dev@googlegroups.com>
homepage: https://github.com/flutter/plugins/tree/master/packages/sensors
-version: 0.4.1+2
+version: 0.4.1+3
flutter:
plugin:
@@ -20,6 +20,7 @@
flutter_test:
sdk: flutter
e2e: ^0.2.0
+ mockito: ^4.1.1
environment:
sdk: ">=2.0.0-dev.28.0 <3.0.0"
diff --git a/packages/sensors/test/sensors_test.dart b/packages/sensors/test/sensors_test.dart
index 603f805..1485d58 100644
--- a/packages/sensors/test/sensors_test.dart
+++ b/packages/sensors/test/sensors_test.dart
@@ -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';
@@ -16,44 +15,67 @@
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();
+ final AccelerometerEvent event = await accelerometerEvents.first;
- 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) {},
- );
- }
+ expect(event.x, sensorData[0]);
+ expect(event.y, sensorData[1]);
+ expect(event.z, sensorData[2]);
+ });
- bool isCanceled = false;
+ 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);
+
+ 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');
- }
- });
+ BinaryMessages.handlePlatformMessage(
+ channelName,
+ event,
+ (ByteData reply) {},
+ );
+ }
- final AccelerometerEvent event = await accelerometerEvents.first;
- expect(event.x, 1.0);
- expect(event.y, 2.0);
- expect(event.z, 3.0);
-
- 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');
+ }
});
}