Unregistering Listeners on our device when we close the app (for Battery Life!)
@Override
protected void onStop() {
super.onStop();
// Unregister all sensor listeners in this callback so they don't
// continue to use resources when the app is stopped.
mSensorManager.unregisterListener(this);
}
finally implement the SensorEventListener so we can register changes
public class MainActivity extends AppCompatActivity implements SensorEventListener {
We want to generate a rotation matrix from the raw accelerometer and magnetometer data. which helps to use in the next step to get the device orientation.
Rotation Matrix
A rotation matrix is a linear algebra term that translates the sensor data from one coordinate system to another—in this case, from the device's coordinate system to the Earth's coordinate system. That matrix is an array of nine float values, because each point (on all three axes) is expressed as a 3D vector.
The device-coordinate system is a standard 3-axis (x, y, z) coordinate system relative to the device's screen when it is held in the default or natural orientation. Most sensors use this coordinate system. In this orientation:
The x-axis is horizontal and points to the right edge of the device.
The y-axis is vertical and points to the top edge of the device.
The z-axis extends up from the surface of the screen. Negative z values are behind the screen.
The Earth's coordinate system is also a 3-axis system, but relative to the surface of the Earth itself. In the Earth's coordinate system:
The y-axis points to magnetic north along the surface of the Earth.
The x-axis is 90 degrees from y, pointing approximately east.
The z-axis extends up into space. Negative z extends down into the ground.
A reference to the array for the rotation matrix is passed into the getRotationMatrix() method and modified in place. The second argument to getRotationMatrix() is an inclination matrix, which you don't need for this app. You can use null for this argument.
The getRotationMatrix() method returns a boolean (the rotationOK variable), which is true if the rotation was successful. The boolean might be false if the device is free-falling (meaning that the force of gravity is close to 0), or if the device is pointed very close to magnetic north. The incoming sensor data is unreliable in these cases, and the matrix can't be calculated. Although the boolean value is almost always true, it's good practice to check that value anyhow.
Azimuth: The direction (north/south/east/west) the device is pointing. 0 is magnetic north.
Pitch: The top-to-bottom tilt of the device. 0 is flat.
Roll: The left-to-right tilt of the device. 0 is flat.
All three angles are measured in radians, and range from -π (-3.141) to π.
@Override
public void onSensorChanged(SensorEvent event) {
int sensorType = event.sensor.getType();
switch (sensorType) {
case Sensor.TYPE_ACCELEROMETER:
mAccelerometerData = event.values.clone();
break;
case Sensor.TYPE_MAGNETIC_FIELD:
mMagnetometerData = event.values.clone();
break;
default:
return;
}
float[] rotationMatrix = new float[9];
boolean rotationOK = SensorManager.getRotationMatrix(rotationMatrix, null, mAccelerometerData, mMagnetometerData)
float orientationValues[] = new float[3];
if (rotationOK) {
SensorManager.getOrientation(rotationMatrix, orientationValues);
};
float azimuth = orientationValues[0];
float pitch = orientationValues[1];
float roll = orientationValues[2];
mTextSensorAzimuth.setText(getResources().getString(R.string.value_format, azimuth));
mTextSensorPitch.setText(getResources().getString(R.string.value_format, pitch));
mTextSensorRoll.setText(getResources().getString(R.string.value_format, roll));
}
onSensorChange() : if the change is not enough, set it to 0.
Set up the alpha to 0 to prevent retaining old values.
if (Math.abs(pitch) < 0.5f) {
pitch = 0;
}
if (Math.abs(roll) < 0.5f) {
roll = 0;
}
mSpotTop.setAlpha(0f);
mSpotBottom.setAlpha(0f);
mSpotLeft.setAlpha(0f);
mSpotRight.setAlpha(0f);
if (pitch > 0) {
mSpotBottom.setAlpha(pitch);
} else {
mSpotTop.setAlpha(Math.abs(pitch));
}
if (roll > 0) {
mSpotLeft.setAlpha(roll);
} else {
mSpotRight.setAlpha(Math.abs(roll));
}
For the TiltSpot app you're only interested in displaying dots in response to some device tilt, not the full range. This means that you can conveniently use the radian units directly as input to the alpha.