为什么总是希望用户点击触摸屏上的按钮? 通过使用当今中端Android手机上可用的一些硬件传感器,您可以创建能够提供更引人入胜的用户体验的应用程序。
传感器框架是Android SDK的一部分,可让您以轻松,一致的方式从大多数传感器(无论是硬件还是软件)读取原始数据。 在本教程中,我将向您展示如何使用该框架从两个非常常见的传感器(接近传感器和陀螺仪)读取数据。 我还将向您介绍旋转矢量传感器,它是一种复合传感器,在大多数情况下,它可以作为陀螺仪的一种更简单,更准确的替代方法。
先决条件
要继续进行,您需要满足以下条件:
- 带有接近传感器和陀螺仪的Android设备
- 最新版本的Android Studio
1.项目设置
如果您的应用无法在没有所需硬件传感器的设备上完全无法使用,则不应将其安装在此类设备上。 您可以通过向Android Studio项目的清单文件中添加一个或多个<uses-feature>
标签来让Google Play和其他应用市场了解您的应用对硬件的要求。
我们将在本教程中创建的应用无法在缺少接近传感器和陀螺仪的设备上运行。 因此,将以下行添加到清单文件中:
<uses-feature
android:name="android.hardware.sensor.proximity"
android:required="true" />
<uses-feature
android:name="android.hardware.sensor.gyroscope"
android:required="true" />
但是请注意,由于<uses-feature>
标记对用户使用其APK文件手动安装您的应用没有帮助,因此您仍必须在使用前以编程方式检查传感器是否可用。
2.使用接近传感器
为了避免意外的触摸事件,电话的触摸屏在靠近耳朵时会变黑。 有没有想过您的手机如何确定它是否靠近您的耳朵? 好吧,它使用了接近传感器,它是一种硬件传感器,可以判断物体是否靠近它。 尽管它们的最大范围通常只有大约5 cm,但一些接近传感器也可以告诉物体有多远。
现在,让我们创建一个活动,每次将手悬停在设备的接近传感器上时,其背景颜色都会变为红色。
步骤1:获取接近传感器
要访问任何硬件传感器,您需要一个SensorManager
对象。 要创建它,请使用Activity
类的getSystemService()
方法并将SENSOR_SERVICE
常量传递给它。
SensorManager sensorManager =
(SensorManager) getSystemService(SENSOR_SERVICE);
现在,您可以通过调用getDefaultSensor()
方法并将TYPE_PROXIMITY
常量传递给它来为接近传感器创建一个Sensor
对象。
Sensor proximitySensor =
sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
在继续之前,请始终确保Sensor
对象不为null
。 如果是,则表示接近传感器不可用。
if(proximitySensor == null) {
Log.e(TAG, "Proximity sensor not available.");
finish(); // Close app
}
步骤2:注册听众
为了能够读取传感器生成的原始数据,必须通过调用SensorManager
对象的registerListener()
方法将SensorEventListener
与之关联。 这样做时,还必须指定应多久从传感器读取一次数据。
以下代码注册了一个侦听器,该侦听器允许您每两秒钟读取一次接近传感器的数据:
// Create listener
SensorEventListener proximitySensorListener = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent sensorEvent) {
// More code goes here
}
@Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
};
// Register it, specifying the polling interval in
// microseconds
sensorManager.registerListener(proximitySensorListener,
proximitySensor, 2 * 1000 * 1000);
我建议您始终在活动的onResume()
方法中注册侦听器,并在onPause()
方法中取消注册侦听器。 这是注销注销侦听器的方法:
sensorManager.unregisterListener(proximitySensorListener);
步骤3:使用原始数据
在onSensorChanged()
方法内可用的SensorEvent
对象具有一个values
数组,其中包含关联传感器生成的所有原始数据。 对于接近传感器,该数组包含单个值,该值指定传感器与附近物体之间的距离(以厘米为单位)。
如果该值等于传感器的最大范围,则可以安全地假设附近没有东西。 相反,如果小于最大范围,则表示附近有东西。 您可以使用关联的Sensor
对象的getMaximumRange()
方法确定任何硬件传感器的最大范围。
要根据接近传感器的数据实际更改活动的背景颜色,可以使用顶层窗口装饰视图的setBackgroundColor()
方法。
因此,将以下代码添加到上一步中创建的onSensorChanged()
方法中:
if(sensorEvent.values[0] < proximitySensor.getMaximumRange()) {
// Detected something nearby
getWindow().getDecorView().setBackgroundColor(Color.RED);
} else {
// Nothing is nearby
getWindow().getDecorView().setBackgroundColor(Color.GREEN);
}
如果您现在运行该应用程序,并将手悬停在手机的顶部边缘,则应该看到屏幕变成红色。

3.使用陀螺仪
陀螺仪可让您确定任何给定时刻的Android设备的角速度。 简单来说,它告诉您设备围绕其X,Y和Z轴旋转的速度。 最近,即使是廉价手机也内置了陀螺仪,而增强现实和虚拟现实应用程序变得如此流行。
通过使用陀螺仪,您可以开发可响应设备方向的微小变化的应用程序。 若要查看操作方法,现在让我们创建一个活动,每次您沿Z轴以逆时针方向旋转手机时,其背景颜色都会变为蓝色,否则会变为黄色。
步骤1:获取陀螺仪
要为陀螺仪创建Sensor
对象,只需将TYPE_GYROSCOPE
常量传递给SensorManager
对象的getDefaultSensor()
方法即可。
gyroscopeSensor =
sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
步骤2:注册听众
为陀螺仪传感器创建侦听器与为接近传感器创建侦听器没有什么不同。 但是,在注册时,必须确保其采样频率很高。 因此,建议您使用SENSOR_DELAY_NORMAL
常量,而不是指定以微秒为单位的轮询间隔。
// Create a listener
gyroscopeSensorListener = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent sensorEvent) {
// More code goes here
}
@Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
};
// Register the listener
sensorManager.registerListener(gyroscopeSensorListener,
gyroscopeSensor, SensorManager.SENSOR_DELAY_NORMAL);
步骤3:使用原始数据
陀螺仪传感器的原始数据由三个float
值组成,用于指定设备沿X,Y和Z轴的角速度。 每个值的单位是弧度每秒。 如果沿任何轴逆时针旋转,则与该轴关联的值将为正。 如果顺时针旋转,它将为负。
因为我们目前仅对沿Z轴的旋转感兴趣,所以我们将仅使用SensorEvent
对象的values
数组中的第三个元素。 如果大于0.5f
,我们可以在很大程度上确保逆时针旋转,并将背景色设置为蓝色。 同样,如果它小于-0.5f
,我们可以将背景色设置为黄色。
if(sensorEvent.values[2] > 0.5f) { // anticlockwise
getWindow().getDecorView().setBackgroundColor(Color.BLUE);
} else if(sensorEvent.values[2] < -0.5f) { // clockwise
getWindow().getDecorView().setBackgroundColor(Color.YELLOW);
}
如果现在运行该应用程序,将手机保持为纵向模式,然后将其向左倾斜,则应该会看到活动变为蓝色。 如果您以相反的方向倾斜它,它应该变成黄色。

但是,如果您将手机转动太多,其屏幕方向将变为横向,并且您的活动将重新开始。 为避免这种情况,建议您在清单文件中将活动的screenOrientation
设置为portrait
。
<activity
android:name=".GyroscopeActivity"
android:screenOrientation="portrait">
</activity>
4.使用旋转矢量传感器
如今,大多数开发人员更喜欢软件,复合传感器而不是硬件传感器。 一个软件传感器结合了来自多个硬件传感器的低级原始数据,以生成不仅易于使用而且更加准确的新数据。 接近传感器没有其他软件。 但是,陀螺仪有两个:游戏旋转矢量传感器和旋转矢量传感器。 在本教程中,我们仅关注后者。
在上一步的示例中,每次沿Z轴的角速度在顺时针或逆时针方向上大于0.5 rad / s时,我们都会更改活动的背景颜色。 但是,以角速度进行工作并不直观。 此外,我们不知道旋转之前或之后设备的实际角度是多少。
通过使用旋转矢量传感器,现在让我们创建一个活动,其活动背景色仅在旋转特定角度时才会改变。 例如,每当它绕Z轴旋转超过45°时,我们就可以将其变为黄色;当其旋转在-10°和10°之间时,可以将其变为白色;而当其旋转小于-45°时,可以将其变为蓝色。
第1步:设置旋转矢量传感器
要获取旋转矢量传感器,必须将TYPE_ROTATION_VECTOR
常量传递给SensorManager
对象的getDefaultSensor()
方法。
rotationVectorSensor =
sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
使用软件传感器与使用硬件传感器没有什么不同。 因此,您现在必须将侦听器与旋转矢量传感器相关联,以便能够读取其数据。 您可以再次将SENSOR_DELAY_NORMAL
常量用于轮询间隔。
// Create a listener
rvListener = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent sensorEvent) {
// More code goes here
}
@Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
};
// Register it
sensorManager.registerListener(rvListener,
rotationVectorSensor, SensorManager.SENSOR_DELAY_NORMAL);
步骤2:使用资料
旋转矢量传感器结合了由陀螺仪,加速度计和磁力计生成的原始数据,以创建四元数 。 因此,其SensorEvent
对象的values
数组具有以下五个元素:
- 四元数的X,Y,Z和W分量
- 航向精度
您可以使用SensorManager
类的getRotationMatrixFromVector()
方法将四元数转换为旋转矩阵(4x4矩阵getRotationMatrixFromVector()
。
float[] rotationMatrix = new float[16];
SensorManager.getRotationMatrixFromVector(
rotationMatrix, sensorEvent.values);
如果要开发OpenGL应用程序,则可以直接使用旋转矩阵在3D场景中变换对象。 但是,现在,让我们将旋转矩阵转换为方向数组,指定设备沿Z,X和Y轴的旋转。 为此,我们可以使用SensorManager
类的getOrientation()
方法。
在调用getOrientation()
方法之前,必须重新映射旋转矩阵的坐标系。 更准确地说,必须旋转旋转矩阵,以使新坐标系的Z轴与原始坐标系的Y轴重合。
// Remap coordinate system
float[] remappedRotationMatrix = new float[16];
SensorManager.remapCoordinateSystem(rotationMatrix,
SensorManager.AXIS_X,
SensorManager.AXIS_Z,
remappedRotationMatrix);
// Convert to orientations
float[] orientations = new float[3];
SensorManager.getOrientation(remappedRotationMatrix, orientations);
默认情况下, orientations
数组包含以弧度表示的角度而不是度数。 如果您习惯弧度,请随时直接使用。 否则,请使用以下代码将其所有角度转换为度:
for(int i = 0; i < 3; i++) {
orientations[i] = (float)(Math.toDegrees(orientations[i]));
}
现在,您可以基于orientations
数组的第三个元素来更改活动的背景色。
if(orientations[2] > 45) {
getWindow().getDecorView().setBackgroundColor(Color.YELLOW);
} else if(orientations[2] < -45) {
getWindow().getDecorView().setBackgroundColor(Color.BLUE);
} else if(Math.abs(orientations[2]) < 10) {
getWindow().getDecorView().setBackgroundColor(Color.WHITE);
}
如果您现在运行该应用程序,将手机置于纵向模式,然后将其顺时针或逆时针倾斜超过45°,您应该会看到背景颜色发生变化。

结论
在本教程中,您学习了如何使用Android的传感器框架来创建可响应接近传感器和陀螺仪生成的数据的应用程序。 您还学习了如何使用旋转矢量传感器(一种比陀螺仪更流行的替代方法)工作。 随意以创新的方式使用传感器。 但是请注意,使用传感器效率低下的应用可能会很快耗尽设备的电池电量。
翻译自: https://code.tutsplus.com/tutorials/android-sensors-in-depth-proximity-and-gyroscope--cms-28084