Working with Sensors
1. Accessing Sensor Service
| Property | Description | Example |
|---|---|---|
| SensorManager | Class to access sensor data | SensorManager sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); |
| Sensor.TYPE_ACCELEROMETER | Constant for accelerometer sensor | sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); |
| Sensor.TYPE_GYROSCOPE | Constant for gyroscope sensor | sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE); |
| Sensor.TYPE_LIGHT | Constant for light sensor | sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); |
| Sensor.TYPE_MAGNETIC_FIELD | Constant for magnetic field sensor | sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); |
| Sensor.TYPE_PROXIMITY | Constant for proximity sensor | sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); |
| Sensor.TYPE_TEMPERATURE | Constant for temperature sensor | sensorManager.getDefaultSensor(Sensor.TYPE_TEMPERATURE); |
Example: Registering a Sensor Listener
class MainActivity : AppCompatActivity() {
private lateinit var sensorManager: SensorManager
private lateinit var accelerometer: Sensor
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
}
override fun onResume() {
super.onResume()
sensorManager.registerListener(sensorEventListener, accelerometer, SensorManager.SENSOR_DELAY_NORMAL)
}
override fun onPause() {
super.onPause()
sensorManager.unregisterListener(sensorEventListener)
}
private val sensorEventListener = object : SensorEventListener {
override fun onSensorChanged(event: SensorEvent?) {
event?.let {
val x = it.values[0]
val y = it.values[1]
val z = it.values[2]
// Process sensor data
}
}
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {}
}
}
2. Listing Available Sensors
| Sensor Type | Description | Usage | Notes |
|---|---|---|---|
| TYPE_ACCELEROMETER | Measures acceleration force in m/s² along a device's X, Y, and Z axis. | Used for motion detection, tilt sensing, and gesture recognition. | NEW in Android 13 |
| TYPE_GYROSCOPE | Measures the rate of rotation in rad/s around a device's X, Y, and Z axis. | Used for 3D orientation tracking and camera stabilization. | NEW in Android 13 |
| TYPE_LIGHT | Measures the ambient light level in lux. | Used for automatic screen brightness adjustment. | Deprecated since Android 10 |
| TYPE_MAGNETIC_FIELD | Measures the ambient magnetic field in μT for X, Y, and Z axis. | Used for compass functionality and navigation. | NEW in Android 13 |
| TYPE_PROXIMITY | Measures the proximity of an object in cm to the device sensor. | Used for screen off when phone is near ear during calls. | NEW in Android 13 |
| TYPE_TEMPERATURE | Measures the ambient air temperature in Celsius. | Used for environmental monitoring and health tracking. | Deprecated since Android 10 |
Example: Listing Available Sensors
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensors = sensorManager.getSensorList(Sensor.TYPE_ALL)
for (sensor in sensors) {
println("Sensor Name: ${sensor.name}")
println("Sensor Type: ${sensor.type}")
println("Vendor: ${sensor.vendor}")
println("Version: ${sensor.version}")
}
3. Registering Sensor Listeners
| Method | Description | Parameters | Notes |
|---|---|---|---|
| registerListener() | Registers a sensor listener to receive sensor events | listener: SensorEventListener, sensor: Sensor, delay: Int |
Must be called on the main thread. Delay values are defined in SensorManager. |
| unregisterListener() | Unregisters a sensor listener | listener: SensorEventListener |
Must be called to prevent memory leaks and unnecessary battery drain. |
Example: Registering a Sensor Listener
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
val sensorListener = object : SensorEventListener {
override fun onSensorChanged(event: SensorEvent) {
val x = event.values[0]
val y = event.values[1]
val z = event.values[2]
// Process sensor data
}
override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {
// Handle accuracy changes
}
}
sensorManager.registerListener(sensorListener, accelerometer, SensorManager.SENSOR_DELAY_NORMAL)
Note: Always unregister listeners in
onPause() or onStop() to avoid memory leaks.
Key Points
- Use
SensorManagerto access sensors. - Implement
SensorEventListenerto handle sensor data. - Register listeners with appropriate delay values for performance.
4. Unregistering Listeners
Unregistering listeners is crucial to prevent memory leaks and unnecessary resource consumption. Android provides methods to unregister sensor listeners.
| Method | Description | Notes |
|---|---|---|
| SensorManager.unregisterListener() | Unregisters a sensor listener | Must be called to clean up resources |
Example: Unregistering a Sensor Listener
class MainActivity : AppCompatActivity() {
private lateinit var sensorManager: SensorManager
private lateinit var accelerometer: Sensor
private val sensorListener = object : SensorEventListener {
override fun onSensorChanged(event: SensorEvent) {
// Handle sensor data
}
override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {
// Handle accuracy changes
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)!!
}
override fun onResume() {
super.onResume()
sensorManager.registerListener(sensorListener, accelerometer, SensorManager.SENSOR_DELAY_NORMAL)
}
override fun onPause() {
super.onPause()
sensorManager.unregisterListener(sensorListener) // Unregister listener
}
}
Note: Always unregister listeners in
onPause() or onStop() to prevent memory leaks and ensure proper cleanup.5. Handling Sensor Events
| Event Type | Description | Parameters | Notes |
|---|---|---|---|
| onSensorChanged | Called when sensor data is updated | SensorEvent |
Triggered by sensor hardware or system |
| onAccuracyChanged | Called when sensor accuracy changes | Sensor, accuracy |
Use to adjust sensor behavior based on accuracy level |
Example: Registering Sensor Listener
class SensorActivity : AppCompatActivity(), SensorEventListener {
private lateinit var sensorManager: SensorManager
private lateinit var accelerometer: Sensor
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
}
override fun onResume() {
super.onResume()
sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL)
}
override fun onPause() {
super.onPause()
sensorManager.unregisterListener(this)
}
override fun onSensorChanged(event: SensorEvent) {
val x = event.values[0]
val y = event.values[1]
val z = event.values[2]
// Process sensor data
}
override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {
// Handle accuracy changes
}
}
Note: Always unregister listeners in
onPause to prevent memory leaks and unnecessary battery drain.Sensor Event Handling Workflow
- Implement
SensorEventListenerinterface - Get
SensorManagerinstance - Register listener with desired sensor and delay
- Override
onSensorChangedto process new data - Override
onAccuracyChangedto handle accuracy updates - Unregister listener in
onPause
6. Using Accelerometer
| Property | Description | Values |
|---|---|---|
| sensorType | Defines the type of sensor | SENSOR_TYPE_ACCELEROMETER |
| resolution | Minimum change in acceleration that triggers a sensor event | 0.01 m/s² |
| powerConsumption | Estimated power consumption in mA | 0.15 mA |
Example: Reading Accelerometer Data
class AccelerometerActivity : AppCompatActivity(), SensorEventListener {
private lateinit var sensorManager: SensorManager
private var accelerometer: Sensor? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
}
override fun onSensorChanged(event: SensorEvent) {
val x = event.values[0]
val y = event.values[1]
val z = event.values[2]
Log.d("Accelerometer", "X: $x, Y: $y, Z: $z")
}
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {}
}
Note: Ensure that the app has
android.permission.ACCESS_FINE_LOCATION if location-based sensor data is required.
Warning: Accelerometer readings can be affected by device orientation and external forces. Always validate sensor data in your application logic.
7. Working with Gyroscope
| Property | Description | Notes |
|---|---|---|
| Sensor.TYPE_GYROSCOPE | Identifies the gyroscope sensor | Available on most modern Android devices |
| Sensor.TYPE_GYROSCOPE_UNCALIBRATED | Provides uncalibrated gyroscope data | Includes bias values for calibration |
Example: Reading Gyroscope Data
class GyroscopeActivity : AppCompatActivity() {
private lateinit var sensorManager: SensorManager
private var gyroscopeSensor: Sensor? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
gyroscopeSensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE)
}
override fun onSensorChanged(event: SensorEvent) {
val x = event.values[0]
val y = event.values[1]
val z = event.values[2]
// Process gyroscope data
Log.d("Gyroscope", "X: $x, Y: $y, Z: $z")
}
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {}
}
Example: Registering Sensor Listener
class MainActivity : AppCompatActivity() {
private lateinit var sensorManager: SensorManager
private var gyroscopeSensor: Sensor? = null
override fun onResume() {
super.onResume()
gyroscopeSensor?.let {
sensorManager.registerListener(sensorEventListener, it, SensorManager.SENSOR_DELAY_NORMAL)
}
}
override fun onPause() {
super.onPause()
sensorManager.unregisterListener(sensorEventListener)
}
private val sensorEventListener = object : SensorEventListener {
override fun onSensorChanged(event: SensorEvent) {
if (event.sensor.type == Sensor.TYPE_GYROSCOPE) {
val rotationVector = event.values
// Use rotation vector for orientation calculations
}
}
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {}
}
}
Note: Gyroscope data is in radians per second. For accurate orientation calculations, consider using
RotationVector or Quaternion methods.
Warning: Not all devices have a gyroscope sensor. Always check for sensor availability before registering listeners.
8. Using Proximity Sensor
| Property | Description | Values |
|---|---|---|
| Sensor.TYPE_PROXIMITY | Proximity sensor type identifier | 8 |
| sensorManager | Instance of SensorManager to access sensors | SensorManager |
| proximitySensor | Proximity sensor object | Sensor |
Example: Registering Proximity Sensor
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val proximitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY)
val sensorEventListener = object : SensorEventListener {
override fun onSensorChanged(event: SensorEvent) {
val distance = event.values[0]
if (distance == 0f) {
// Object is close to sensor
println("Object detected near proximity sensor")
} else {
// Object is far from sensor
println("Object not detected near proximity sensor")
}
}
override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {}
}
sensorManager.registerListener(sensorEventListener, proximitySensor, SensorManager.SENSOR_DELAY_NORMAL)
Note: The proximity sensor typically returns a value of
0.0f when an object is close to the sensor and a higher value when it's farther away. The exact distance depends on the device.
9. Working with Light Sensor
| Property | Description | Values |
|---|---|---|
| sensor.type | Light sensor type | TYPE_LIGHT |
| sensor.resolution | Resolution in lux | 0.1 |
| sensor.power | Power consumption in mA | 0.15 |
Example: Reading Light Sensor Data
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
class LightSensorActivity : AppCompatActivity(), SensorEventListener {
private lateinit var sensorManager: SensorManager
private var lightSensor: Sensor? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_light_sensor)
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
lightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT)
}
override fun onSensorChanged(event: SensorEvent?) {
if (event?.sensor?.type == Sensor.TYPE_LIGHT) {
val lightValue = event.values[0]
// Process light value (lux)
}
}
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
// Handle sensor accuracy changes
}
override fun onResume() {
super.onResume()
lightSensor?.let { sensorManager.registerListener(this, it, SensorManager.SENSOR_DELAY_NORMAL) }
}
override fun onPause() {
super.onPause()
sensorManager.unregisterListener(this)
}
}
Note: Light sensor values are reported in lux units. The sensor provides a single value representing ambient light intensity.
10. Monitoring Device Orientation
| Property | Description | Values |
|---|---|---|
| orientation | Current device orientation | ORIENTATION_UNKNOWN, ORIENTATION Portrait, ORIENTATION_LANDSCAPE |
| rotation | Rotation of the device in degrees | 0, 90, 180, 270 |
Example: Detecting Orientation Changes
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
class OrientationSensorActivity : AppCompatActivity(), SensorEventListener {
private lateinit var sensorManager: SensorManager
private var orientationSensor: Sensor? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
orientationSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION)
}
override fun onSensorChanged(event: SensorEvent?) {
if (event?.sensor?.type == Sensor.TYPE_ORIENTATION) {
val orientation = event.values[0]
when (orientation.toInt()) {
0 -> {
// Portrait
}
90 -> {
// Landscape (right)
}
180 -> {
// Portrait (upside down)
}
270 -> {
// Landscape (left)
}
}
}
}
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {}
override fun onResume() {
super.onResume()
sensorManager.registerListener(this, orientationSensor, SensorManager.SENSOR_DELAY_NORMAL)
}
override fun onPause() {
super.onPause()
sensorManager.unregisterListener(this)
}
}
Note: The
TYPE_ORIENTATION sensor is deprecated as of Android API level 30. Use TYPE_GAME_ROTATION_VECTOR or TYPE_ROTATION_VECTOR for better accuracy.
Warning: Orientation sensor data can be inaccurate on devices with low-quality sensors or when the device is in a non-standard position.