拿到 Android 设备的陀螺仪数据并不复杂。通过 SensorManager 拿到服务实例后,先检查一下硬件是不是支持 TYPE_GYROSCOPE——绝大多数手机都有,但显式做个判断没坏处。接着注册监听器,采样频率看场景选:游戏里用 SENSOR_DELAY_GAME 能得到大概 50Hz 的更新,旋转屏幕之类用 SENSOR_DELAY_UI 大约 15Hz,功耗更低。
回调在 onSensorChanged 里触发,SensorEvent.values 三个分量分别是绕 X、Y、Z 轴的角速度,单位是弧度/秒。方向可以按右手定则来记:拇指指向轴的正方向,四指弯过去就是正旋转。手机平放时 Z 轴朝上,逆时针拧动就是正转。
不过角速度只是瞬时值,我们通常想知道总共转了多少度。这就需要对角速度做积分:把每次读到的速度乘两次回调之间的时间差,再累加起来。
event.timestamp 给了纳秒精度的时间戳,算差值时记得转换成秒。我第一次写这段的时候没转换,角度值一下蹿到好几百,还以为传感器抽了。
积分逻辑写出来大概是这样:
private static final float NS2S = 1.0f / 1000000000.0f; // 纳秒转秒系数
private float timestamp;
private float[] angle = new float[3]; // 累积 X,Y,Z 轴旋转角度
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_GYROSCOPE) {
if (timestamp != 0) {
// 计算与上一次回调的时间差(秒)
final float dT = (event.timestamp - timestamp) * NS2S;
// 对三个轴的角速度分别进行积分
angle[0] += event.values[0] * dT; // X 轴角度累积
angle[1] += event.values[1] * dT;
angle[] += event.values[] * dT;
timestamp = event.timestamp;
} {
timestamp = event.timestamp;
}
}
}

