Skip to content

Instantly share code, notes, and snippets.

@rayliverified
Created May 25, 2020 18:13
Show Gist options
  • Save rayliverified/219f075f7b8bd29488ce9863b807a85c to your computer and use it in GitHub Desktop.
Save rayliverified/219f075f7b8bd29488ce9863b807a85c to your computer and use it in GitHub Desktop.
Flutter Shake Detection Attempt (algorithm doesn't filter events well)
import 'dart:async';
import 'package:rxdart/rxdart.dart';
import 'package:sensors/sensors.dart';
Stream<bool> isShaking() {
final timeout = Duration(milliseconds: 300);
final accelerationThreshold = 3;
final sampleInterval = Duration(milliseconds: 50);
final moveCountThreshold = 5;
Stream<bool> extractShake(Stream<UserAccelerometerEvent> stream) async* {
int moveCount = 0;
var lastSampleAt = DateTime.now();
double lastX = 0;
double lastY = 0;
double lastZ = 0;
bool _isReverted(num now, num rev) {
return now * rev <= 0;
}
bool _isMoving(num now) {
return now.abs() >= accelerationThreshold;
}
await for (final e in stream) {
final now = DateTime.now();
final sinceLast = now.difference(lastSampleAt);
if (sinceLast < sampleInterval) continue;
if (sinceLast > timeout) {
moveCount = 0;
}
lastSampleAt = now;
if (!_isMoving(e.x) && !_isMoving(e.y) && !_isMoving(e.z)) continue;
final bool isShaking = (_isMoving(e.x) && _isReverted(e.x, lastX)) ||
(_isMoving(e.y) && _isReverted(e.y, lastY)) ||
(_isMoving(e.z) && _isReverted(e.z, lastZ));
lastX = e.x;
lastY = e.y;
lastZ = e.z;
if (isShaking) moveCount++;
if (moveCount >= moveCountThreshold) yield true;
}
}
final Stream<bool> shake = userAccelerometerEvents
.transform(StreamTransformer.fromBind((stream) => extractShake(stream)));
return shake
.switchMap((e) => TimerStream(false, timeout).startWith(e))
.startWith(false);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment