In this tutorial, we’ll be digging deep into the world of Android Sensors. Our smartphones are much more than just speed, UI and animations.
Android Sensors
Android Sensors contains properties to detect changes in the environment such as light, proximity, rotation, movements, magnetic fields and much more.
Broadly speaking, the Android Sensors fall under the following categories:
- Environment Sensors
- Motion Sensors
- Orientation and Position Sensors
To access the various Sensors in Android, you must use the SensorManager
class.
Following code shows how to initialize a SensorManager
:
SensorManager sensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
Next, you can use the Sensor class to instantiate the specific Sensor.
Sensor lightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
Next, you can register the sensor using the following code:
sensorManager.registerListener(this, lightSensor,
SensorManager.SENSOR_DELAY_NORMAL);
It’s recommended to register the listener in the onResume()
method and unregister it in the onPause
method in order to save battery power.
In order to listen to sensor events, you can implement the SensorEventListener
interface in the activity.
You need to override the following methods for that:
@Override
public void onSensorChanged(SensorEvent event) {
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
To get a list of all the available sensors on the device, use the following code:
List<Sensor> sensorList = sensorManager.getSensorList(Sensor.TYPE_ALL);
String sensorInfo = "";
for (Sensor s : sensorList){
sensorInfo= sensorInfo + s.getName()+ "n";
}
In the next section, we’ll discuss some of the common types of Sensors.
Android Sensors Types
- Photometer is used to sense and control the brightness. Besides, there are sensors for pressure, humidity, and temperature.
- For movements, Accelerometer is used to detect shakes/tilt gestures.
- Proximity Sensors are used to detect how close the object is to the device. It’s commonly present in Call Applications. As you bring the phone close to the ear, the screen goes black, thanks to this sensor. Though the maximum range of proximity is 5 cms.
- Gyroscope is used to measure rotation/spin. Gravity sensors are used to measure the force of gravity.
- Magneto Meter is used to get the device position.
- Pedometer is used to detect the number of steps the user takes.
Following image depicts a few sensor types and their event data values with the respective formats.
Android Sensors Types
How to Check if Android Sensor is Available?
Some devices don’t support certain Sensors. So you can simply add the permissions in the Manifest file.
Google ensures that the Application on the Play store would not be visible to users with unsupported devices.
<uses-feature android:name="android.hardware.accelerometer"
android:required="true" />
<uses-feature android:name="android.hardware.sensor.proximity"
android:required="true" />
<uses-feature android:name="android.hardware.sensor.gyroscope"
android:required="true" />
Accelerometer is not available on Android Emulators.
In the next section, we’ll implement certain sensors in our Android Application.
Android Sensors Example Project Structure
Android Sensor Example Project Structure
Android Sensors Example Code
The code for the activity_main.xml
is given below:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_margin="16dp"
android:gravity="center"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/btnAccelerometer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="accelerometerSensorOnClick"
android:text="Accelerometer" />
<Button
android:id="@+id/btnProximity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="proximitySensorOnClick"
android:text="Proximity Sensor" />
<Button
android:id="@+id/btnGyro"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="gyroscopeSensorOnClick"
android:text="Gyroscope" />
<Button
android:id="@+id/btnLightSensor"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="lightSensorOnClick"
android:text="Light Sensor" />
<Button
android:id="@+id/btnStepCounterOnClick"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="stepCounterOnClick"
android:text="Step Counter Sensor" />
<Button
android:id="@+id/btnAmbientTemp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="ambientTempSensorOnClick"
android:text="Ambient Temperature Sensor" />
<TextView
android:id="@+id/tvResult"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Values would be entered here..." />
</LinearLayout>
The code for the MainActivity.java is given below:
package com.journaldev.androidsensors;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity implements SensorEventListener {
private TextView textView;
private SensorManager sensorManager;
private Sensor accelerometerSensor;
private Sensor proximitySensor;
private Sensor lightSensor;
private Sensor stepCounterSensor;
private Sensor tempSensor;
private Sensor gyroscopeSensor;
private int currentSensor;
private long lastUpdate = 0;
private float last_x, last_y, last_z;
private static final int SHAKE_THRESHOLD = 600;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.tvResult);
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
accelerometerSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
proximitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
lightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
stepCounterSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);
gyroscopeSensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
tempSensor = sensorManager.getDefaultSensor(Sensor.TYPE_AMBIENT_TEMPERATURE);
}
public boolean checkSensorAvailability(int sensorType) {
boolean isSensor = false;
if (sensorManager.getDefaultSensor(sensorType) != null) {
isSensor = true;
}
return isSensor;
}
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == currentSensor) {
if (currentSensor == Sensor.TYPE_LIGHT) {
float valueZ = event.values[0];
textView.setText("Brightness " + valueZ);
} else if (currentSensor == Sensor.TYPE_PROXIMITY) {
float distance = event.values[0];
textView.setText("Proximity " + distance);
} else if (currentSensor == Sensor.TYPE_STEP_DETECTOR) {
float steps = event.values[0];
textView.setText("Steps : " + steps);
} else if (currentSensor == Sensor.TYPE_ACCELEROMETER) {
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
long curTime = System.currentTimeMillis();
if ((curTime - lastUpdate) > 100) {
long diffTime = (curTime - lastUpdate);
lastUpdate = curTime;
float speed = Math.abs(x + y + z - last_x - last_y - last_z) / diffTime * 10000;
if (speed > SHAKE_THRESHOLD) {
Toast.makeText(getApplicationContext(), "Your phone just shook", Toast.LENGTH_LONG).show();
}
last_x = x;
last_y = y;
last_z = z;
}
} else if (currentSensor == Sensor.TYPE_GYROSCOPE) {
if (event.values[2] > 0.5f) {
textView.setText("Anti Clock");
} else if (event.values[2] < -0.5f) {
textView.setText("Clock");
}
} else if (currentSensor == Sensor.TYPE_AMBIENT_TEMPERATURE) {
textView.setText("Ambient Temp in Celsius :" + event.values[0]);
}
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
public void accelerometerSensorOnClick(View view) {
if (checkSensorAvailability(Sensor.TYPE_ACCELEROMETER)) {
currentSensor = Sensor.TYPE_ACCELEROMETER;
}
textView.setText("Accelerometer not available");
}
public void proximitySensorOnClick(View view) {
if (checkSensorAvailability(Sensor.TYPE_PROXIMITY)) {
currentSensor = Sensor.TYPE_PROXIMITY;
}
textView.setText("Proximity Sensor not available");
}
public void gyroscopeSensorOnClick(View view) {
if (checkSensorAvailability(Sensor.TYPE_GYROSCOPE)) {
currentSensor = Sensor.TYPE_GYROSCOPE;
} else {
textView.setText("Gyroscope Sensor not available");
}
}
public void lightSensorOnClick(View view) {
if (checkSensorAvailability(Sensor.TYPE_LIGHT)) {
currentSensor = Sensor.TYPE_LIGHT;
} else {
textView.setText("Light Sensor not available");
}
}
public void stepCounterOnClick(View view) {
if (checkSensorAvailability(Sensor.TYPE_STEP_DETECTOR)) {
currentSensor = Sensor.TYPE_STEP_DETECTOR;
} else {
textView.setText("Step Counter Sensor not available");
}
}
public void ambientTempSensorOnClick(View view) {
if (checkSensorAvailability(Sensor.TYPE_AMBIENT_TEMPERATURE)) {
currentSensor = Sensor.TYPE_AMBIENT_TEMPERATURE;
} else {
textView.setText("Ambient Temperature Sensor not available");
}
}
@Override
protected void onResume() {
super.onResume();
sensorManager.registerListener(this, accelerometerSensor,
SensorManager.SENSOR_DELAY_NORMAL);
sensorManager.registerListener(this, lightSensor,
SensorManager.SENSOR_DELAY_NORMAL);
sensorManager.registerListener(this, proximitySensor,
SensorManager.SENSOR_DELAY_NORMAL);
sensorManager.registerListener(this, stepCounterSensor,
SensorManager.SENSOR_DELAY_NORMAL);
sensorManager.registerListener(this, tempSensor,
SensorManager.SENSOR_DELAY_NORMAL);
sensorManager.registerListener(this, gyroscopeSensor,
SensorManager.SENSOR_DELAY_NORMAL);
}
@Override
protected void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
}
}
For the accelerometer, we need to get the position of all the three coordinates from each of the three axes. The accelerometer is so sensitive that it keeps updating these points.
In order to detect whether it’s a shake or not, we take the difference of the points within a given time frame to detect how quickly they moved.
The gyroscope detects whether the phone is rotated anticlockwise or clockwise in the z plane.
Light sensor’s hardware is located at the top of the phone to the right of the front camera lens.
The output of the above application in action is given below. Since we cannot show a live demo, we’ve just displayed the sensor value for brightness.
Android Sensors App Output
That brings an end to this android sensors tutorial. You can download the project from the link below.