For a recent project, I had to create a game-style controller Android app that senses the phone’s tilt and uses it as an input.
(image via SO)
To simplify the explanation, imagine a jet thruster game where the farther you tilt the phone back, the stronger the jet thrusters fire:
- When the phone sits upright, the thrusters don’t fire at all
- When the phone is tilted all the way back, the thrusters fire at full force
Going into it, I knew I would need to use Sensors, specifically something about the Accelerometer. Digging in a bit more, no amount of Googling/Stack searching provided me with exactly what I was looking for, so I figured I’d write it up here…
Initial search results:
- A few pretty quiet SO posts with no real solutions
- A pretty extensive SO overview of Android orientation
- A solution that remaps the actual returned coordinate system
- which led me down the path of SensorManager.remapCoordinateSystem() (not where I needed to be)
- and this solution for measuring the tilt of the XY plane which does a lot of the math, which I’m assuming was written prior to the Android SDK providing some of the convenience methods.
Solution
My fully open-sourced solution lives here: https://github.com/loisaidasam/tilt
Specifically, check out MainActivity.java:
- It sets up the sensor listeners
- listens for sensor updates
- uses SensorManager.getRotationMatrix()
- and then SensorManager.getOrientation() to get
azimuth
,pitch
, androll
- From there, we convert the radians returned in
roll
to degrees - and then apply the results to a 0-100 scale
A few notes:
It seems that the TYPE_ORIENTATION sensor type was deprecated in favor of SensorManager.getOrientation()
Another thing to keep in mind is the orientation of your device, which is subject to change despite settings you’ve applied in your app – check out this Android Developers Blog post “One Screen Turn Deserves Another”. It highlights always checking your device orientation using Display.getRotation(), comparing constants such as ROTATION_0, ROTATION_90, etc.