首页 / Android 入门教程 / 传感器基础

Android 入门教程

传感器基础

本教程共 100 篇 · 第 91 篇 · 更新于 2026-07-28 · 约 7 分钟阅读

AndroidAndroid 入门教程传感器SensorManager加速度计计步器

91. 传感器基础

本节目标:学会用 SensorManager 读取加速度计、陀螺仪、光线传感器等数据,掌握注册监听、设置延迟、处理生命周期,理解计步器等常见用法。

Android 手机里塞了一堆传感器:加速度计、陀螺仪、光线、距离、磁力计、心率等。应用能通过 SensorManager 读这些数据,做计步、屏幕旋转、计方向等功能。

传感器分类

三大类:

  • 运动传感器:测设备运动。加速度计、陀螺仪、重力传感器、线性加速度。
  • 环境传感器:测环境。光线、温度、气压、湿度。
  • 位置传感器:测设备方位。磁力计、接近传感器、GPS(位置传感器不在 SensorManager 管,用 LocationManager)。

获取 SensorManager

val sensorManager = context.getSystemService(SensorManager::class.java)

列出所有传感器

val sensors = sensorManager.getSensorList(Sensor.TYPE_ALL)
sensors.forEach { sensor ->
    Log.d("Sensor", "${sensor.name} - type=${sensor.stringType}")
}

调试时跑一遍能看你的设备有什么传感器。

加速度计示例

最常见的传感器,测三个轴的加速度(含重力)。

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

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

    override fun onResume() {
        super.onResume()
        accelerometer?.let {
            sensorManager.registerListener(this, it, SensorManager.SENSOR_DELAY_NORMAL)
        }
    }

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

    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]
            // x、y、z 单位是 m/s²
            Log.d("Accel", "x=$x, y=$y, z=$z")
        }
    }

    override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
        // 精度变化,一般不用管
    }
}

要点:

  • 实现 SensorEventListener 接口。
  • registerListener 注册监听,第三个参数是延迟级别。
  • onResume 注册,onPause 注销,省电。
  • event.values 是浮点数组,不同传感器含义不同。

延迟级别

registerListener 的第三参数控制数据更新频率:

级别延迟用途
SENSOR_DELAY_FASTEST0 微秒最高频率,耗电大,特殊场景
SENSOR_DELAY_GAME20ms游戏
SENSOR_DELAY_UI60msUI 更新
SENSOR_DELAY_NORMAL200ms普通,省电
Warning

选高级别耗电严重。计步用 NORMAL 就够,游戏用 GAME。别无脑用 FASTEST。

陀螺仪

测角速度,三个轴的旋转速度(弧度/秒):

val gyroscope = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE)

override fun onSensorChanged(event: SensorEvent) {
    if (event.sensor.type == Sensor.TYPE_GYROSCOPE) {
        val x = event.values[0]  // 绕 X 轴角速度
        val y = event.values[1]
        val z = event.values[2]
    }
}

陀螺仪和加速度计一起用,能算出设备姿态(欧拉角、四元数),用于 AR、游戏控制。

光线传感器

环境光强度,单位勒克斯(lux)。用来自动调亮度:

val lightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT)

override fun onSensorChanged(event: SensorEvent) {
    if (event.sensor.type == Sensor.TYPE_LIGHT) {
        val lux = event.values[0]  // 光照强度
        // 亮(>100 lux)就调高屏幕亮度
    }
}

接近传感器

测物体到屏幕的距离(厘米),打电话时熄屏用:

val proximitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY)

override fun onSensorChanged(event: SensorEvent) {
    if (event.sensor.type == Sensor.TYPE_PROXIMITY) {
        val distance = event.values[0]  // 距离,单位 cm
        // 接近耳朵(< 5cm)就锁屏
    }
}

计步器

Android 4.4(API 19)起有两种计步传感器:

  • TYPE_STEP_DETECTOR:每走一步触发一次事件。
  • TYPE_STEP_COUNTER:从开机累计步数,应用关闭也继续。
val stepCounter = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER)

override fun onSensorChanged(event: SensorEvent) {
    if (event.sensor.type == Sensor.TYPE_STEP_COUNTER) {
        val totalSteps = event.values[0].toInt()
        // 累计步数
    }
}
Note

计步器是硬件传感器,没有的设备 getDefaultSensor 返回 null。要判空。

磁力计

测磁场强度,配合加速度计算方向:

val magneticField = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD)
val accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)

override fun onSensorChanged(event: SensorEvent) {
    if (event.sensor.type == Sensor.TYPE_ACCELEROMETER) {
        System.arraycopy(event.values, 0, gravity, 0, 3)
    } else if (event.sensor.type == Sensor.TYPE_MAGNETIC_FIELD) {
        System.arraycopy(event.values, 0, geomagnetic, 0, 3)
    }

    val rotationMatrix = FloatArray(9)
    val orientation = FloatArray(3)
    SensorManager.getRotationMatrix(rotationMatrix, null, gravity, geomagnetic)
    SensorManager.getOrientation(rotationMatrix, orientation)

    val azimuth = Math.toDegrees(orientation[0].toDouble())  // 方位角
    val pitch = Math.toDegrees(orientation[1].toDouble())    // 俯仰
    val roll = Math.toDegrees(orientation[2].toDouble())     // 翻滚
}

方位角就是指南针的角度(0 度朝北)。

Compose 里用

把传感器数据封装成 Flow:

@Composable
fun accelerometerFlow(): Flow<FloatArray>? {
    val context = LocalContext.current
    val sensorManager = remember { context.getSystemService(SensorManager::class.java) }
    val sensor = remember { sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) }

    return remember(sensor) {
        sensor?.let {
            callbackFlow {
                val listener = object : SensorEventListener {
                    override fun onSensorChanged(event: SensorEvent) {
                        trySend(event.values)
                    }
                    override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {}
                }
                sensorManager.registerListener(listener, it, SensorManager.SENSOR_DELAY_NORMAL)

                awaitClose {
                    sensorManager.unregisterListener(listener)
                }
            }
        }
    }
}

@Composable
fun TiltIndicator() {
    val accelFlow = accelerometerFlow()
    var tilt by remember { mutableStateOf(0f) }

    LaunchedEffect(accelFlow) {
        accelFlow?.collect { values ->
            tilt = values[0]  // x 轴加速度
        }
    }

    Text("倾斜:$tilt")
}

传感器精度

onAccuracyChanged 告诉你传感器精度变化:

override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
    when (accuracy) {
        SensorManager.SENSOR_STATUS_NO_CONTACT -> // 没接触
        SensorManager.SENSOR_STATUS_UNRELIABLE -> // 不可靠
        SensorManager.SENSOR_STATUS_ACCURACY_LOW -> // 低精度
        SensorManager.SENSOR_STATUS_ACCURACY_MEDIUM -> // 中精度
        SensorManager.SENSOR_STATUS_ACCURACY_HIGH -> // 高精度
    }
}

精度低时可以提示用户校准(比如磁力计可以画 8 字校准)。

常见坑

  1. onPause 忘记 unregister:传感器一直跑,耗电严重。
  2. 延迟级别太高:FASTEST 级别几秒钟电就掉一大截。
  3. 不判 null 就用:设备没这传感器,getDefaultSensor 返回 null,崩。
  4. 主线程做重计算:传感器回调在主线程,复杂算法切子线程。
  5. 方向用 TYPE_ORIENTATION:已废弃。用加速度计 + 磁力计 + getRotationMatrix
  6. 同一传感器注册多个 listener:合并到一个,省电。

小结

SensorManager 读传感器:getDefaultSensor 拿传感器,registerListener 注册监听,onResume/onPause 管理生命周期。延迟级别按场景选,NORMAL 够日常用。加速度计测运动,磁力计测方向,计步器走 TYPE_STEP_COUNTER。Compose 里把传感器数据封装成 Flow,自动管理订阅。

下一章讲位置与地图。