Have you ever played mobile games like Subway Surfers or Temple Run and wondered how the position of the runner changes?
Have you ever counted the number of steps/distance you’ve walked in a day? Have you ever used a compass in your phone and wondered how it works?
Or ever thought about while talking to a person through your phone, how the phone’s screen goes black when you bring it close to your ear?
Table of contents:
1. Introduction to Sensors
In Android devices, there are various built-in sensors that can be used to measure a device’s orientation, its motion, and various other kinds of environmental conditions. In general, there are two types of sensors in Android devices:
- Hardware sensors: Hardware-based sensors are physical components built into a handset or tablet device. They derive their data by directly measuring specific environmental properties, such as acceleration, geomagnetic field strength, or angular change.
- Software sensors: Software-based sensors are not physical devices, although they mimic hardware-based sensors. Software-based sensors derive their data from one or more of the hardware-based sensors and are sometimes called virtual sensors or synthetic sensors. The linear acceleration sensor and the gravity sensor are examples of software-based sensors.
It is pretty much possible for an android device to have a different number of sensors, i.e it’s not necessary that all the devices must have all the sensors. Also, it’s possible for a particular device may have more than one sensor of the same type but with different configurations and capabilities.
To express data values or to collect data, the sensors in Android devices use a 3-axis coordinate system i.e. you will be having X, Y, and Z-axis. The following figure depicts the position of various axis used in sensors.
2. Types of Sensors
- Environment sensors– These help in identifying environmental properties like temperature, pressure, humidity, etc. Some of the examples of environmental sensors include thermometers, barometers, etc.
- Motion sensors– These sensors are responsible for measuring or identifying the shakes and tilts of your Android devices. These sensors measure the rotational forces along three axes. Gravity sensors and accelerometers are two examples of motion sensors.
- Position sensors– Position sensors are useful for determining a device’s physical position in the world’s frame of reference. For example, you can use the geomagnetic field sensor in combination with the accelerometer to determine a device’s position relative to the magnetic north pole. Magnetometers and proximity sensors are two examples of position sensors.
3. Android Sensor API Framework
Android’s Sensor API provides many classes and interfaces. The most important classes and interfaces are as follows:
- SensorManager: This class is used to access various sensors present in the device.
- Sensor: This class is used to create an instance of a specific sensor you want to use.
- SensorEvent: This class is used to find the details of sensor events.
- SensorEventListener: This is used to receive notifications from the SensorManager whenever there’s new sensor data or any change in its values.
You can use these sensor-related APIs to:
- Find the sensors that are active and present on a device and determine their capabilities.
- Monitor various sensor events to collect data and use them accordingly.
Implementing Sensors in Android
1. Identify Device Sensors
First, we need to identify the sensors that are present on a given device by getting a reference to the sensor service.
To do so, create an instance of the SensorManager class by calling the getSystemService() method and passing in the SENSOR_SERVICE argument:
private lateinit var sensorManager: SensorManager
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
Next, you can get a listing of every sensor on a device by calling the getSensorList() method and using the TYPE_ALL constant.
If you want to list all of the sensors of a given type, you could use another constant instead of TYPE_ALL, such as TYPE_GYROSCOPE, TYPE_LINEAR_ACCELERATION, or TYPE_GRAVITY. You can also determine whether a specific type of sensor exists on a device by using the getDefaultSensor() method and passing in the type constant for a specific sensor.
Apart from finding the list of available sensors, we can also check the capability of a particular sensor; i.e. we can check the resolution, power, range, etc. of a particular sensor.
//To get a list of all sensors present on the device.
val deviceSensors: List<Sensor> = sensorManager.getSensorList(Sensor.TYPE_ALL)
//To get the default gravity sensor present on the device
val gravSensor = sensorManager.getDefaultSensor(TYPE_GRAVITY)
//To check the power of the sensor if present
val power = gravSensor.getPower()
2. Register a SensorEventListener
This is used to receive notifications from the SensorManager when there’s new sensor data.
The SensorEventListener interface has two callback methods:
- onAccuracyChanged(): This is called when there is a change in the accuracy of the measurement of the sensor. It returns the Sensor object that has changed and the new accuracy status, some of them are:-
- SENSOR_STATUS_ACCURACY_LOW: Reports data with low accuracy; therefore, calibration with the environment is needed.
- SENSOR_STATUS_ACCURACY_MEDIUM: Reports data with an average level of accuracy; calibration with the environment may improve the readings.
- SENSOR_STATUS_ACCURACY_HIGH: Reports the data with maximum accuracy.
- SENSOR_STATUS_UNRELIABLE: The values returned by this sensor cannot be trusted; calibration is needed or the environment doesn’t allow readings.
- SENSOR_STATUS_NO_CONTACT: The values returned by this sensor cannot be trusted because the sensor had no contact with what it was measuring (for example, the heart rate monitor is not in contact with the user).
2. onSensorChanged(): This is called when new sensor data is available. This method will provide you with a SensorEvent object that contains new/changed sensor data.
package com.lavanya.androidsensors
import android.content.Context
import android.graphics.Color
import android.hardware.Sensor
import android.hardware.Sensor.TYPE_GRAVITY
import android.hardware.Sensor.TYPE_PROXIMITY
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity(), SensorEventListener {
private lateinit var sensorManager: SensorManager
private lateinit var gravSensor: Sensor
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val listOfSensors = sensorManager.getSensorList(Sensor.TYPE_ALL)
//To see the details of the sensor
listOfSensors.forEach {
Log.d("TAG", "Name : " + it.name)
Log.d("TAG", "Type : " + it.stringType)
...
}
gravSensor = sensorManager.getDefaultSensor(TYPE_GRAVITY)
}
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
//This is called whenever the accuracy of the sensor in use changes.
//Perform the action.
}
override fun onSensorChanged(event: SensorEvent?) {
//If there is a new sensor data. Perform the action.
}
//Registering a SensorEventListener
override fun onResume() {
super.onResume()
gravSensor?.also { it ->
sensorManager.registerListener(this, it, SensorManager.SENSOR_DELAY_NORMAL)
}
}
//Unregistering a SensorEventListener
override fun onPause() {
super.onPause()
sensorManager.unregisterListener(this)
}
}
Conclusion
In this blog, we learned about a range of Android sensors (both hardware- and software-based) and their types that are present in Android devices.
We used the Android Sensor API to determine the sensors present in the Android device. And finally, we saw how to use SensorEventListener to handle new sensor data.
Always remember to unregister the listener when not in use to avoid power and memory issues. Also, sensor data may change anytime, so don’t block the onSensorChanged() method. And above all, before collecting data from a sensor, make sure that sensor is present in the device because not all Android devices have the same sensors 😉.
Link to the GitHub repository:
Thanks for reading! If you enjoyed this story, please click the 👏 button and share it to help others find it!
Have feedback? Let’s connect on Twitter.
Comments 0 Responses