Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use the sensor flutter package for developing a step counter?

I am trying to make a step counter with the help of sensor flutter widget, I was having the look at sensor flutter package code but not getting a single point from where to start and how to achieve the required result.

What are the things involved in making a step with the help of sensor flutter widget? or Can I also do it Google Fit Api in a flutter app to create a custom step counter?

I have added the

dependencies:
  sensors: "^0.3.3"

to the pubspec.yaml

main.dart

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:sensors/sensors.dart';

import 'snake.dart';

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Sensors Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  final String title;

  MyHomePage({Key key, this.title}) : super(key: key);

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  static const int _snakeRows = 20;
  static const int _snakeColumns = 20;
  static const double _snakeCellSize = 10.0;

  List<double> _accelerometerValues;
  List<double> _userAccelerometerValues;
  List<double> _gyroscopeValues;
  List<StreamSubscription<dynamic>> _streamSubscriptions =
  <StreamSubscription<dynamic>>[];

  @override
  Widget build(BuildContext context) {
    final List<String> accelerometer =
    _accelerometerValues?.map((double v) => v.toStringAsFixed(1))?.toList();
    final List<String> gyroscope =
    _gyroscopeValues?.map((double v) => v.toStringAsFixed(1))?.toList();
    final List<String> userAccelerometer = _userAccelerometerValues
        ?.map((double v) => v.toStringAsFixed(1))
        ?.toList();

    return new Scaffold(
      appBar: new AppBar(
        title: const Text('Sensor Example'),
      ),
      body: new Column(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: <Widget>[
          new Center(
            child: new DecoratedBox(
              decoration: new BoxDecoration(
                border: new Border.all(width: 1.0, color: Colors.black38),
              ),
              child: new SizedBox(
                height: _snakeRows * _snakeCellSize,
                width: _snakeColumns * _snakeCellSize,
                child: new Snake(
                  rows: _snakeRows,
                  columns: _snakeColumns,
                  cellSize: _snakeCellSize,
                ),
              ),
            ),
          ),
          new Padding(
            child: new Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: <Widget>[
                new Text('Accelerometer: $accelerometer'),
              ],
            ),
            padding: const EdgeInsets.all(16.0),
          ),
          new Padding(
            child: new Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: <Widget>[
                new Text('UserAccelerometer: $userAccelerometer'),
              ],
            ),
            padding: const EdgeInsets.all(16.0),
          ),
          new Padding(
            child: new Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: <Widget>[
                new Text('Gyroscope: $gyroscope'),
              ],
            ),
            padding: const EdgeInsets.all(16.0),
          ),
        ],
      ),
    );
  }

  @override
  void dispose() {
    super.dispose();
    for (StreamSubscription<dynamic> subscription in _streamSubscriptions) {
      subscription.cancel();
    }
  }

  @override
  void initState() {
    super.initState();
    _streamSubscriptions
        .add(accelerometerEvents.listen((AccelerometerEvent event) {
      setState(() {
        _accelerometerValues = <double>[event.x, event.y, event.z];
      });
    }));
    _streamSubscriptions.add(gyroscopeEvents.listen((GyroscopeEvent event) {
      setState(() {
        _gyroscopeValues = <double>[event.x, event.y, event.z];
      });
    }));
    _streamSubscriptions
        .add(userAccelerometerEvents.listen((UserAccelerometerEvent event) {
      setState(() {
        _userAccelerometerValues = <double>[event.x, event.y, event.z];
      });
    }));
  }
}

snake.dart

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

import 'package:flutter/material.dart';
import 'package:sensors/sensors.dart';

class Snake extends StatefulWidget {
  final int rows;
  final int columns;
  final double cellSize;
  Snake({this.rows = 20, this.columns = 20, this.cellSize = 10.0}) {
    assert(10 <= rows);
    assert(10 <= columns);
    assert(5.0 <= cellSize);
  }

  @override
  State<StatefulWidget> createState() =>
      new SnakeState(rows, columns, cellSize);
}

class SnakeBoardPainter extends CustomPainter {
  GameState state;
  double cellSize;

  SnakeBoardPainter(this.state, this.cellSize);

  @override
  void paint(Canvas canvas, Size size) {
    final Paint blackLine = new Paint()..color = Colors.black;
    final Paint blackFilled = new Paint()
      ..color = Colors.black
      ..style = PaintingStyle.fill;
    canvas.drawRect(
      new Rect.fromPoints(Offset.zero, size.bottomLeft(Offset.zero)),
      blackLine,
    );
    for (math.Point<int> p in state.body) {
      final Offset a = new Offset(cellSize * p.x, cellSize * p.y);
      final Offset b = new Offset(cellSize * (p.x + 1), cellSize * (p.y + 1));

      canvas.drawRect(new Rect.fromPoints(a, b), blackFilled);
    }
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return true;
  }
}

class SnakeState extends State<Snake> {
  double cellSize;
  GameState state;
  AccelerometerEvent acceleration;

  SnakeState(int rows, int columns, this.cellSize) {
    state = new GameState(rows, columns);
  }

  @override
  Widget build(BuildContext context) {
    return new CustomPaint(painter: new SnakeBoardPainter(state, cellSize));
  }

  @override
  void initState() {
    super.initState();
    accelerometerEvents.listen((AccelerometerEvent event) {
      setState(() {
        acceleration = event;
      });
    });

    new Timer.periodic(const Duration(milliseconds: 200), (_) {
      setState(() {
        _step();
      });
    });
  }

  void _step() {
    final math.Point<int> newDirection = acceleration == null
        ? null
        : acceleration.x.abs() < 1.0 && acceleration.y.abs() < 1.0
        ? null
        : (acceleration.x.abs() < acceleration.y.abs())
        ? new math.Point<int>(0, acceleration.y.sign.toInt())
        : new math.Point<int>(-acceleration.x.sign.toInt(), 0);
    state.step(newDirection);
  }
}

class GameState {
  int rows;
  int columns;
  int snakeLength;
  GameState(this.rows, this.columns) {
    snakeLength = math.min(rows, columns) - 5;
  }

  List<math.Point<int>> body = <math.Point<int>>[const math.Point<int>(0, 0)];
  math.Point<int> direction = const math.Point<int>(1, 0);

  void step(math.Point<int> newDirection) {
    math.Point<int> next = body.last + direction;
    next = new math.Point<int>(next.x % columns, next.y % rows);

    body.add(next);
    if (body.length > snakeLength) body.removeAt(0);
    direction = newDirection ?? direction;
  }
}
like image 934
Tushar Rai Avatar asked Jun 02 '18 10:06

Tushar Rai


1 Answers

So, building off of what noogui commented:

Google Fit API can be found in one of dart.dev's plugins: https://pub.dev/packages/googleapis. This is actually a collection of all the Google APIs, so it includes Google Fit among others.

More specifically, here at https://github.com/dart-lang/googleapis/blob/master/generated/googleapis/lib/fitness/v1.dart

And as noogui mentioned, this runs off of the REST API:

  • https://developers.google.com/fit/rest
  • https://developers.google.com/fit/rest/v1/reference

The plugin site doesn't have examples on how to use it, only samples on how to get your auth started, so you'll have to reference the main docs for a guide:

  • Android sample: https://github.com/android/fit-samples/blob/master/StepCounter/app/src/main/java/com/google/android/gms/fit/samples/stepcounter/MainActivity.java
  • Data Types: https://developers.google.com/fit/rest/v1/data-types
    • com.google.step_count.delta
  • https://developers.google.com/fit/rest/v1/data-sources
    • derived:com.google.step_count.delta:com.google.android.gms:estimated_steps
  • https://developers.google.com/fit/scenarios/record-steps
  • https://developers.google.com/fit/scenarios/read-daily-step-total
    • https://www.googleapis.com/fitness/v1/users/me/dataset:aggregate
like image 128
TWL Avatar answered Oct 25 '22 22:10

TWL