123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- import 'dart:async';
- import 'package:flutter/services.dart';
- import 'dart:io' show Platform;
- const int _stopped = 0, _walking = 1;
- class Pedometer {
- static const EventChannel _stepDetectionChannel =
- const EventChannel('step_detection');
- static const EventChannel _stepCountChannel =
- const EventChannel('step_count');
- static StreamController<PedestrianStatus> _androidPedestrianController =
- StreamController.broadcast();
- /// Returns one step at a time.
- /// Events come every time a step is detected.
- static Stream<PedestrianStatus> get pedestrianStatusStream {
- Stream<PedestrianStatus> stream = _stepDetectionChannel
- .receiveBroadcastStream()
- .map((event) => PedestrianStatus._(event));
- if (Platform.isAndroid) return _androidStream(stream);
- return stream;
- }
- /// Transformed stream for the Android platform
- static Stream<PedestrianStatus> _androidStream(
- Stream<PedestrianStatus> stream) {
- /// Init a timer and a status
- Timer t;
- int pedestrianStatus;
- /// Listen for events on the original stream
- /// Transform these events by using the timer
- stream.listen((dynamic e) {
- /// If an event is received it means the status is 'walking'
- /// If the timer has been started, it should be cancelled
- /// to prevent sending out additional 'walking' events
- if (t != null) {
- t.cancel();
- /// If a previous status was either not set yet, or was 'stopped'
- /// then a 'walking' event should be emitted.
- if (pedestrianStatus == null || pedestrianStatus == _stopped) {
- _androidPedestrianController.add(PedestrianStatus._(_walking));
- pedestrianStatus = _walking;
- }
- }
- /// After receiving an event, start a timer for 2 seconds, after
- /// which a 'stopped' event is emitted. If it manages to go through,
- /// it is because no events were received for the 2 second duration
- t = Timer(Duration(seconds: 2), () {
- _androidPedestrianController.add(PedestrianStatus._(_stopped));
- pedestrianStatus = _stopped;
- });
- });
- return _androidPedestrianController.stream;
- }
- /// Returns the steps taken since last system boot.
- /// Events may come with a delay.
- static Stream<StepCount> get stepCountStream => _stepCountChannel
- .receiveBroadcastStream()
- .map((event) => StepCount._(event));
- static Stream<int> get stepDetectionStream => _stepDetectionChannel
- .receiveBroadcastStream()
- .map((event) => event as int);
- }
- /// A DTO for steps taken containing the number of steps taken.
- class StepCount {
- DateTime _timeStamp;
- int _steps = 0;
- StepCount._(dynamic e) {
- _steps = e as int;
- _timeStamp = DateTime.now();
- }
- int get steps => _steps;
- DateTime get timeStamp => _timeStamp;
- @override
- String toString() =>
- 'Steps taken: $_steps at ${_timeStamp.toIso8601String()}';
- }
- /// A DTO for steps taken containing a detected step and its corresponding
- /// status, i.e. walking, stopped or unknown.
- class PedestrianStatus {
- static const _WALKING = 'walking';
- static const _STOPPED = 'stopped';
- static const _UNKNOWN = 'unknown';
- static const Map<int, String> _STATUSES = {
- _stopped: _STOPPED,
- _walking: _WALKING
- };
- DateTime _timeStamp;
- String _status = _UNKNOWN;
- PedestrianStatus._(dynamic t) {
- int _type = t as int;
- _status = _STATUSES[_type];
- _timeStamp = DateTime.now();
- }
- String get status => _status;
- DateTime get timeStamp => _timeStamp;
- @override
- String toString() => 'Status: $_status at ${_timeStamp.toIso8601String()}';
- }
|