传感器基础
本教程共 100 篇 · 第 91 篇 · 更新于 2026-07-28 · 约 7 分钟阅读
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_FASTEST | 0 微秒 | 最高频率,耗电大,特殊场景 |
SENSOR_DELAY_GAME | 20ms | 游戏 |
SENSOR_DELAY_UI | 60ms | UI 更新 |
SENSOR_DELAY_NORMAL | 200ms | 普通,省电 |
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 字校准)。
常见坑
onPause忘记 unregister:传感器一直跑,耗电严重。- 延迟级别太高:FASTEST 级别几秒钟电就掉一大截。
- 不判 null 就用:设备没这传感器,
getDefaultSensor返回 null,崩。 - 主线程做重计算:传感器回调在主线程,复杂算法切子线程。
- 方向用
TYPE_ORIENTATION:已废弃。用加速度计 + 磁力计 +getRotationMatrix。 - 同一传感器注册多个 listener:合并到一个,省电。
小结
用 SensorManager 读传感器:getDefaultSensor 拿传感器,registerListener 注册监听,onResume/onPause 管理生命周期。延迟级别按场景选,NORMAL 够日常用。加速度计测运动,磁力计测方向,计步器走 TYPE_STEP_COUNTER。Compose 里把传感器数据封装成 Flow,自动管理订阅。
下一章讲位置与地图。