[Flutter] Proper shake detection in Shaky Rock-Paper-Scissors

Shake the phone and when you stop the random result will be shown on your screen. Going to be easy, right? Well, not quite so. This is going to be a brief article about how I’ve got to an acceptable solution.

About Flutter

I’ve been fiddling with Flutter for the last half year and even without knowing much about mobile development and Dart it was fairly easy to get started (coming from mainly web and backend development). The BLOC pattern was weird at first and sometimes I get into widget hell but the rest is awesome. And oh boi, the package manager is so great, it’s blazing fast and just works like every package manager should. (I’m looking at you NPM)

I’m pretty sure that I’ll use Flutter in the future for other projects an I urge you all to give it a try. I have a few other apps in the works already — with more complexity.

One thing for sure, HTML + CSS is still the best for describing UIs, hands down. (Even though it can be slower than it’s native counterpart.)

During my development, I used AnimatedController and TickerProviderStateMixin for my animations.(Read more)

Less straightforward parts

The goal is to spin the twirly background slowly but noticeably. (360deg in 10 seconds).

a) RotatedBox widget but it only supports quarter turns so it’s immediately out.

b) Transform.rotate looks more promising, it has precise angle but as the documentation states: “applies a transformation before painting its child.”

c) Custom painter could do this probably the most efficiently and I would recommend this to you over the others.

d) Using video, gif or sprite as background.

e) Combining Stack, Positioned, Transform.rotate. I discourage you to do this! So, Container by default will be constrained by the screen dimensions so we need to break free by using using Positioned which requires to be a descendant of Stack. Now we can add our Container (with the image) to this Positioned widget (which we apply rotation to). The width and height of the background should be the diameter of the screen (so no black will be shown during rotation). Once again, this is just nasty cheat for achieving this effect.

My Solution was (e) for the time being but I’ll definitely look into (c) later on and might return with an updated solution.

When you tap on the info icon on the right top side the about page will be displayed using a reveal page transition effect, I’ve already did an article about it if you are interested in the details and the source code.

[Circle reveal page route transition in Flutter.]

The goal is to let the user start a shake and perform an action only when the user stops the shaking. On Android, we can use the following sensors (through sensors plugin):

  • TYPE_ACCELEROMETER (Accelerometer): The raw accelerometer data which contains gravitational force (you can get rid of noise using low key pass but there’s more to it).
  • TYPE_LINEAR_ACCELERATION (UserAccelerometer): This provides values without gravitational force but also takes compass and gyroscope into consideration so it provides a more reliable input.

a) Shake plugin provides a basic detection but due to noise and the fact that it uses Accelerometer sensor instead of UserAccelerometer therefore shaking process usually ends while the user still shaking the phone. This is not what we want.

b) Looking into an Android (Java) package, seismic. This looks better, it gets rid of the noise using a queue but it still uses the basic accelerometer and also it requires porting to Dart.

c) Using a queue for noise filtering (like in seismic), switching to UserAccelerometer and introducing a stat module for tracking event frequency (since shake detection requires 50Hz to work properly and sampling cannot be changed yet we have to know it the device is capable of providing sufficient number of events) and invalid event data detection (read more).

My solution was (c) and I still had to cut the shake feature on some phones to make things work properly.

Performance

The FPS is okay at best, I know that (it gets worse when particles are animating). I haven’t digged myself into deeper due to to sheer nature of this project but I feel like rendering transformed FontAwesome icons is the bottleneck.

Conclusion

Thanks for reading, you are more than welcome to leave a comment.

Although the app should work on iOS too, I’m not planning to release it on the AppStore.

Choosing the unknown

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store