← Back to Tutorials Chapter 14

Sensors & Hardware

Android Sensor Framework

Android devices include various sensors that provide data about the device's environment and motion. Use the SensorManager to access them.

class SensorActivity : AppCompatActivity(), SensorEventListener {
    private lateinit var sensorManager: SensorManager
    private var accelerometer: Sensor? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
        accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
    }

    override fun onResume() {
        super.onResume()
        accelerometer?.also { accel ->
            sensorManager.registerListener(this, accel,
                SensorManager.SENSOR_DELAY_NORMAL)
        }
    }

    override fun onSensorChanged(event: SensorEvent) {
        if (event.sensor.type == Sensor.TYPE_ACCELEROMETER) {
            val x = event.values[0]
            val y = event.values[1]
            val z = event.values[2]
            println("Accelerometer: x=$x, y=$y, z=$z")
        }
    }

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

    override fun onPause() {
        super.onPause()
        sensorManager.unregisterListener(this)
    }
}

Sensor Types

CategorySensorsUse Case
MotionAccelerometer, Gyroscope, GravityScreen rotation, gaming, step counting
PositionMagnetometer, ProximityCompass, phone call proximity
EnvironmentLight, Pressure, Temperature, HumidityAuto brightness, weather

Step Counter

class StepCounterService : Service() {
    private lateinit var sensorManager: SensorManager
    private var stepCounter: Sensor? = null

    override fun onCreate() {
        super.onCreate()
        sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
        stepCounter = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER)
    }

    // Register listener
    stepCounter?.let {
        sensorManager.registerListener(listener, it, SensorManager.SENSOR_DELAY_UI)
    }

    private val listener = object : SensorEventListener {
        override fun onSensorChanged(event: SensorEvent) {
            val steps = event.values[0].toInt()
            // Update UI via notification
        }

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

NFC (Near Field Communication)

class NFCActivity : AppCompatActivity() {
    private var nfcAdapter: NfcAdapter? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        nfcAdapter = NfcAdapter.getDefaultAdapter(this)

        if (nfcAdapter == null) {
            Toast.makeText(this, "NFC not available", Toast.LENGTH_SHORT).show()
        }
    }

    // Read NFC tag
    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        if (NfcAdapter.ACTION_TAG_DISCOVERED == intent.action) {
            val tag = intent.getParcelableExtra<Tag>(NfcAdapter.EXTRA_TAG)
            val id = bytesToHex(tag?.id ?: ByteArray(0))
            println("Tag ID: $id")

            // Read NDEF message
            val ndefMessages = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)
            if (ndefMessages != null) {
                val msg = ndefMessages[0] as NdefMessage
                val record = msg.records[0]
                val payload = String(record.payload)
                println("NDEF: $payload")
            }
        }
    }
}

// Manifest
<uses-permission android:name="android.permission.NFC" />
<intent-filter>
    <action android:name="android.nfc.action.NDEF_DISCOVERED" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:mimeType="*/*" />
</intent-filter>

Bluetooth

class BluetoothActivity : AppCompatActivity() {
    private val bluetoothAdapter: BluetoothAdapter? by lazy {
        val manager = getSystemService(BLUETOOTH_SERVICE) as BluetoothManager
        manager.adapter
    }

    // Enable Bluetooth
    fun enableBluetooth() {
        if (bluetoothAdapter?.isEnabled == false) {
            val enableIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
            startActivityForResult(enableIntent, REQUEST_ENABLE_BT)
        }
    }

    // Discover devices
    fun discoverDevices() {
        bluetoothAdapter?.startDiscovery()
    }

    val receiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            when (intent.action) {
                BluetoothDevice.ACTION_FOUND -> {
                    val device = intent.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE)
                    println("Found: ${device?.name} - ${device?.address}")
                }
            }
        }
    }
}
Exercise: Create a fitness app that uses the step counter sensor to track daily steps. Show the step count in a notification. When the user reaches 10,000 steps, show a congratulatory notification. Use the light sensor to adjust the theme (light sensor value below threshold = dark mode).