Sensors Tutorial for Android: Getting Started

In this sensors tutorial, you’ll learn about different types of sensors and how to use sensor fusion (accelerometer with magnetometer) to develop a compass. By Aaqib Hussain.

Leave a rating/review
Download materials
Save for later
Share

Apps use sensors to perform different tasks — in fact, most built-in features of your mobile phone depend on them. For example, touch sensors, proximity sensors, accelerometers, magnetometers and thermometers are all using underlying physical sensors built into a device.

Sensors let devices interact with their surroundings by providing data from a three-dimensional perspective based on the device’s position or motion, or by monitoring the environmental changes to a device’s surroundings.

Sensors are an essential part of every mobile device, improving the overall user experience. A variety of mobile games use sensors such as gyroscopes, accelerometers, and more, enabling users to have a more immersive experience.

In this tutorial, you’ll learn:

  • How to use sensors.
  • What sensor fusion is.
  • What the different types of sensors are and how they work.
  • How to use classes like Sensor, SensorManager and SensorEventListener, which facilitate interacting with sensors on Android devices.

You’ll put this knowledge to work by combining a magnetometer with an accelerometer to develop a functional compass app. By the time you’re done, you’ll be able to start playing around with sensors via the Android API.

Note: This tutorial assumes you have some basic knowledge of Android Studio and Kotlin. If you’re new to Android, check out our Android Tutorials. If you know Android, but are unfamiliar with Kotlin, see Kotlin for Android: An Introduction.

Getting Started

In this tutorial, you’ll work on a sample app called Locaty. You’ll develop this app into a working compass. You’ll also enable reading and processing sensor data while the app is in the background via a persistent notification that will show you the angle and direction your device is facing.

Download the starter project by clicking the Download Materials button at the top or bottom of the tutorial.

Extract the ZIP file and open the starter project in Android Studio 4.0 or later by selecting Open an existing Android Studio project from the welcome screen.

Once the Gradle sync is complete, explore the project structure. The project has two files. Familiarize yourself with the files present — you’ll use them in this tutorial.

Build and run. You’ll see a simple screen with a compass image at the center as below:

starter app

Icon made by smalllikeart

Before you jump into writing any more code, there are some important things you should learn about sensors first. Time to jump over to the next section :]

Types of Sensors

The Android platform supports three broad categories of sensors:

Motion Sensors
These sensors track movement; they include accelerometers, gyroscopes and gravity sensors. They provide data on forces like acceleration and rotation that act on the sensor’s three-dimensional axes.

Environmental Sensors
Barometers and thermometers are types of sensors that access environmental metrics. These sensors monitor environmental variables like air pressure and temperature.

Position Sensors
Magnetometer and orientation sensors help determine the physical position of a device.

Each of these categories represents many specific sensors that are available on a device. You will go through them next.

List of Sensors

Android SDK provides you with a list of various types of sensors that you can use in your app. The availability of these sensors may vary from device to device.

Here’s a quick rundown of each sensor:

  • TYPE_ACCELEROMETER
    Type: Hardware
    Computes the acceleration in m/s2 applied on all three axes (x, y and z), including the force of gravity.
  • TYPE_AMBIENT_TEMPERATURE
    Type: Hardware
    Monitors the temperature of the surroundings in degrees Celsius.
  • TYPE_GRAVITY
    Type: Software or Hardware
    Computes the gravitational force in m/s2 applied on all three axes (x, y and z).
  • TYPE_GYROSCOPE
    Type: Hardware
    Computes the rate of rotation in rad/s around each of the three axes (x, y and z).
  • TYPE_LIGHT
    Type: Hardware
    Evaluates the light around a surrounding in lx units.
  • TYPE_LINEAR_ACCELERATION
    Type: Software or Hardware
    Computes the acceleration force in m/s2 applied on all three axes (x, y and z), excluding the force of gravity.
  • TYPE_MAGNETIC_FIELD
    Type: Hardware
    Computes the geomagnetic field for all three axes in tesla (μT).
  • TYPE_ORIENTATION
    Type: Software
    Computes the degree of rotation around all three axes.
  • TYPE_PRESSURE
    Type: Hardware
    Computes the air pressure in hPa or mbar.
  • TYPE_PROXIMITY
    Type: Hardware
    Computes the proximity of the device’s screen to an object in centimeters.
  • TYPE_RELATIVE_HUMIDITY
    Type: Hardware
    Computes the humidity of the surrounding air as a percentage (%).
  • TYPE_ROTATION_VECTOR
    Type: Software or Hardware
    Computes the orientation of a device by the device’s rotation vector.
  • TYPE_TEMPERATURE
    Type: Hardware
    Monitors the temperature of the surroundings in degrees Celsius. In API 14, the TYPE_AMBIENT_TEMPERATURE sensor replaced this sensor.

Combining Sensor Data With Sensor Fusion

Typically, you can develop a compass just with a magnetometer. If you want more accurate data, however, you can combine a magnetometer with an accelerometer. This method of using data from two or more sensors to get a more accurate result is known as Sensor Fusion.

Now, it’s time to start putting to use all this information. You already have the starter app up and running. You are going to start adding implementation details in order to make the compass functional. Head over to the next section to begin.

Excited Emoji

Setting up Sensors

Open LocatyService.kt and create a variable to hold the reference to SensorManager:

private lateinit var sensorManager: SensorManager

Android Studio now prompts you to import SensorManager, so import android.hardware.SensorManager.

Next, in onCreate, add the following code:

// 1
sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
// 2
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)?.also { accelerometer ->
  sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI)
}
// 3
sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD)?.also { magneticField ->
  sensorManager.registerListener(this, magneticField, SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI)
}

After you add the code above, import android.hardware.Sensor.

Here’s a step-by-step explanation of what the code above does:

  1. Initializes SensorManager.
  2. Registers a sensor event callback to listen to changes in the accelerometer.
  3. Registers a sensor event callback to listen to changes in the magnetometer.

Android SDK provides four constants, which inform the Android system how often to tap into the computed events:

  1. SENSOR_DELAY_FASTEST: Gets sensors data as soon as possible
  2. SENSOR_DELAY_GAME: Gets sensors data at a rate suitable for games
  3. SENSOR_DELAY_UI: Gets sensors data at a rate suitable for working with user interfaces
  4. SENSOR_DELAY_NORMAL: Gets sensors data at a rate suitable for screen orientation changes

To listen to the event changes in the sensors, you need to implement the interface SensorEventListener and override its methods onAccuracyChanged and onSensorChanged.

To do that, start by adding the following imports:

import android.hardware.SensorEvent
import android.hardware.SensorEventListener

After that, implement SensorEventListener in LocatyService:

class LocatyService : Service(), SensorEventListener {

  override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
  }

  override fun onSensorChanged(event: SensorEvent?) {
  }

}

Android system calls onSensorChanged every time there’s a new sensor event. Its SensorEvent parameter gives a set of array of size three, where each index represents a value of an axes in a coordinate system: event.values[0] represents x, event.values[1] represents y and event.values[2] for z.

X, y, and z axes

On the other hand, Android system only calls onAccuracyChanged when there’s a change in accuracy. SensorManager contains all the accuracy change constants in SensorManager.SENSOR_STATUS_*.