Is the Android device lying face up or face down? Or neither?
I tried to keep the
onSensorChanged
method as fast as possible because it can be called many times per second.
The positive
Z
axis points out of the screen of the device;
see
this
diagram.
When lying face up,
the
z
value is positive because the force of gravity that the device experiences
is identical to the force it would experience in the absence of gravity
if it were accelerating in the direction of the positive
Z
axis.
A
falling
object
gains
9.81
meters per second of speed
during each second that it falls.
For an Android device lying face up,
z
should therefore be 9.81,
but the hardware in my Azpen A727 tablet registered 9.96,
and my Amazon Fire HD 6 jittered around 10.1.
Two applications: my cousin’s sailboat, the planetarium in Yonkers.
MainActivity.java
.
The
MainActivity
object acts as the
SensorEventListener
.
R.java
.
Creates the
int
variables
R.layout.activity_main
R.id.textView
R.string.face_up
R.string.face_down
R.string.face_sideways
activity_main.xml
.
strings.xml
.
Contains three
string
resources:
face_up
face_down
face_sideways
AndroidManifest.xml
build.gradle
(Module: app).
Override the methods
onResume
and
onPause
of class
MainActivity
.
(onResume
and
onPause
were originally defined in class
Activity
.
Then they were overridden by the
onResume
and
onPause
in class
FragmentActivity
,
which is a superclass of our
AppCompatActivity
.
We will now override them again.)
Open
MainActivity.java
Click on the whitespace outside
onCreate
but inside the curly braces of class
MainActivity
.
Pull down
Code → Override Methods…
and type
onPause
to search for
onPause
in the drop-down menu.
Press ↓ if necessary.
When you find
onPause
, press OK.
Ocerride
onResume
the same way.
Insert the words
implements
SensorEventListener
.
Then pull down
Code → Implement Methods…
and select
onSensorChanged
and
onAccuracyChanged
.
onSensorChanged
.
if (Math.abs(z) < .5) { s = face_sideways; //z is close to zero } else if (z > 0) { s = face_up; } else { s = face_down; }
onSensorChanged
,
display the value of
z
too.
Round it to two digits to the right of the decimal point,
and display it using a total of at least 6 characters (e.g.,
-10.12
).
To make all the digits the same width,
add the attribute
android:typeface="monospace"
to the
TextView
element in
activity_main.xml
.
To keep the width of the
TextView
constant,
and therefore to keep the position of its left edge constant,
change its
android:layout_width
to
"250dp"
.
textView.setText(s + "\nz = " + String.format("%6.2f", z));Note that z is 9.81 when lying face up, and decreases to zero as we stand the device up.
onSensorChanged
:
0° when lying face up and 90° when standing vertically.
As the device is raised from a prone position,
z
goes from 9.81 to 0.
Therefore the fraction
z/9.81
goes from 1 to 0.
Think of these fractions as the length of the shadow
cast by the device under an overhead sun:
the numbers get smaller as the device become more vertical.
The function arccos gives us the angle created by the fraction.
//The absolute value of a cosine can never be greater than 1. double cosine = z / SensorManager.GRAVITY_EARTH; if (cosine > 1) { cosine = 1; } else if (cosine < -1) { cosine = -1; } //Find the angle that has the given cosine. double radians = Math.acos(cosine); double degrees = Math.toDegrees(radians); textView.setText(s + "\nz = " + String.format("%6.2f", z) + "\n" + String.format("%3.0f", degrees) + "\u00B0"); //Unicode degree symbol