Sensors in Android – Everything You Need to Know

Exploring Android sensor types and the tools to put them to work

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?

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:

  1. 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.
  2. 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 sensorsThese help in identifying environmental properties like temperature, pressure, humidity, etc. Some of the examples of environmental sensors include thermometers, barometers, etc.
  • Motion sensorsThese 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 sensorsPosition 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:

  1. SensorManager: This class is used to access various sensors present in the device.
  2. Sensor: This class is used to create an instance of a specific sensor you want to use.
  3. SensorEvent: This class is used to find the details of sensor events.
  4. 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:

  1. 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:-
  2. SENSOR_STATUS_ACCURACY_LOW: Reports data with low accuracy; therefore, calibration with the environment is needed.
  3. SENSOR_STATUS_ACCURACY_MEDIUM: Reports data with an average level of accuracy; calibration with the environment may improve the readings.
  4. SENSOR_STATUS_ACCURACY_HIGH: Reports the data with maximum accuracy.
  5. SENSOR_STATUS_UNRELIABLE: The values returned by this sensor cannot be trusted; calibration is needed or the environment doesn’t allow readings.
  6. 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 😉.

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.

Avatar photo

Fritz

Our team has been at the forefront of Artificial Intelligence and Machine Learning research for more than 15 years and we're using our collective intelligence to help others learn, understand and grow using these new technologies in ethical and sustainable ways.

Comments 0 Responses

Leave a Reply

Your email address will not be published. Required fields are marked *