传感器概览

大多数 Android 设备都内置了传感器,这些传感器可以测量动作、方向 和各种环境条件的变化。这些传感器能够提供具有高要求的原始数据, 精确度和精确度,在监控三维设备运动或 定位,或者您想要监控设备附近环境环境中的变化。例如, 游戏可能会跟踪设备重力传感器的读数,以推断复杂的用户手势 以及各种动作,例如倾斜、摇晃、旋转或挥动。同样,天气应用程序可能使用 设备的温度传感器和湿度传感器,以计算和报告露点或行程 应用可以使用地磁场传感器和加速度计来报告罗盘 方位。

请参阅以下相关资源:

Android 平台支持三大类传感器:

  • 移动传感器

    这类传感器测量三个轴向上的加速力和旋转力。本次 类别包括加速度计、重力传感器、陀螺仪和旋转矢量传感器 传感器。

  • 环境传感器

    这些传感器测量各种环境参数,例如环境气温 以及压力、照度和湿度。这个类别包括气压计、光度计和 温度计。

  • 位置传感器

    这类传感器测量设备的物理位置。此类别包括: 方向传感器和磁力计。

您可以使用 Android 设备访问设备上的传感器并获取原始传感器数据 传感器框架。传感器框架提供了多个类和接口,可帮助您执行多种 各种与传感器相关的任务。例如,您可以使用传感器框架执行以下操作:

  • 确定设备上有哪些传感器。
  • 确定单个传感器的功能,例如最大范围、制造商、功率 要求和解决方案
  • 获取原始传感器数据并定义获取传感器数据的最低频率。
  • 注册和取消注册用于监控传感器变化的传感器事件监听器。

本主题概述了 Android 平台上可用的传感器。 以及传感器框架。

传感器简介

利用 Android 传感器框架,您可以访问多种类型的传感器。其中一些传感器 基于硬件,有些基于软件。基于硬件的传感器是构建的物理组件 手机或平板设备他们通过直接测量特定环境状况来推导出数据 例如加速度、地磁场强度或角度变化。基于软件 虽然它们模拟了基于硬件的传感器,但它们不是物理设备。基于软件的传感器 从一个或多个基于硬件的传感器获取数据,有时也称为虚拟传感器, 传感器或合成传感器例如,线性加速度传感器和重力传感器 基于软件的传感器。表 1 总结了 Android 支持的传感器 平台。

很少有 Android 设备拥有所有类型的传感器。例如,大多数手机设备和 带有加速度计和磁力计的平板电脑,但配备 气压计或温度计此外,一个设备可以有多个特定类型的传感器。对于 例如,一个设备可以有两个重力传感器,每个重力传感器的范围各不相同。

表 1. Android 平台支持的传感器类型。

传感器 类型 说明 常见用途
TYPE_ACCELEROMETER 硬件 测量施加到设备的加速力(以 m/s2 为单位) 所有三个物理轴(x、y 和 z),包括重力。 移动侦测(摇晃、倾斜等)。
TYPE_AMBIENT_TEMPERATURE 硬件 以摄氏度 (°C) 为单位测量环境室温。请参见下面的备注。 监测气温。
TYPE_GRAVITY 软件或硬件 测量施加到所有设备的重力(以 m/s2 为单位) 三条物理轴(x、y、z)。 移动侦测(摇晃、倾斜等)。
TYPE_GYROSCOPE 硬件 测量设备围绕三维空间的旋转速率(以 rad/s 为单位) 物理轴 (x、y 和 z)。 旋转检测(旋转、转动等)。
TYPE_LIGHT 硬件 测量环境光级(照度),以 lx 为单位。 控制屏幕亮度。
TYPE_LINEAR_ACCELERATION 软件或硬件 测量加速度,以 m/s2 为单位, 应用至某台设备上 所有三个物理轴(x、y 和 z),不包括重力。 监测单个轴向上的加速度。
TYPE_MAGNETIC_FIELD 硬件 测量所有三个物理轴(x、y、z)的环境地磁场 μT。 创建罗盘。
TYPE_ORIENTATION 软件 测量设备围绕所有三个物理轴(x、y、z)进行的旋转度数。 从 API 级别 3 开始,您可以获取 将重力传感器和地磁场传感器与 getRotationMatrix() 方法。 确定设备位置。
TYPE_PRESSURE 硬件 测量环境气压,以 hPa 或 mbar 为单位。 监测气压变化。
TYPE_PROXIMITY 硬件 测量物体相对于视图屏幕的距离(以厘米为单位) 设备。该传感器通常用于确定手机是否被举到 通话过程中手机的位置。
TYPE_RELATIVE_HUMIDITY 硬件 测量环境的相对湿度,以百分比 (%) 表示。 监测露点、绝对湿度和相对湿度。
TYPE_ROTATION_VECTOR 软件或硬件 通过提供设备方向的三个元素来测量设备的屏幕方向, 旋转矢量。 移动侦测和旋转检测。
TYPE_TEMPERATURE 硬件 测量设备的温度,以摄氏度 (°C) 为单位。此传感器 实现方式因设备和设备而异, 此传感器已替换为以下国家/地区中的 TYPE_AMBIENT_TEMPERATURE 传感器: API 级别 14 监测温度。

传感器框架

您可以使用 Android 传感器框架访问这些传感器并获取传感器原始数据。 传感器框架是 android.hardware 软件包的一部分,其中包含以下内容 类和接口:

SensorManager
您可以使用这个类来创建传感器服务的实例。这个类提供了 用于访问和列出传感器、注册和取消注册传感器事件的各种方法 监听器以及获取屏幕方向信息。该类还提供了几个传感器常量, 用于报告传感器准确性、设置数据采集率和校准传感器。
Sensor
您可以使用这个类来创建特定传感器的实例。这个类提供各种 方法,用于确定传感器的特性。
SensorEvent
系统使用此类来创建传感器事件对象,该对象会提供 传感器事件。传感器事件对象包含以下信息:原始传感器数据、 生成该事件的传感器类型、数据的准确性和 事件。
SensorEventListener
您可以使用此接口创建两个回调方法,用于接收通知(传感器 事件)。

在典型的应用中,您可以使用这些与传感器相关的 API 来执行两个基本任务:

  • 识别传感器和传感器功能

    如果您的应用具有 依赖特定传感器类型或功能的功能。例如,您可能希望 识别设备上的所有传感器,并停用所有应用功能 依赖不存在的传感器的应用。同样,您可能需要找出 以便您可以选择性能最佳的传感器实现 。

  • 监控传感器事件

    您可以通过监控传感器事件来获取原始传感器数据。每次都会发生传感器事件 传感器检测到它所测量的参数的变化。传感器事件为您提供 包含四条信息:触发事件的传感器的名称、 事件的时间戳、事件的准确度以及触发的原始传感器数据 事件。

传感器可用性

虽然传感器可用性因设备而异,但也可能因 Android 设备而异 版本。这是因为 Android 传感器是在数个研究阶段引入的 平台版本例如,许多传感器是在 Android 1.5(API 级别 3)中引入的,但有些 未实现,且在 Android 2.3(API 级别 9)之前无法使用。同样, Android 2.3(API 级别 9)和 Android 4.0(API 级别 14)中引入了多个传感器。二 已废弃,取而代之的是更新、更好的传感器。

表 2 总结了每个传感器在不同平台上的可用性。只有四个 之所以列出这些平台,是因为这些平台涉及到传感器变更。传感器 被列为已弃用的平台在后续平台上仍然可用(前提是 传感器),这符合 Android 的向前兼容性政策。

表 2. 传感器在不同平台上的可用性。

传感器 Android 4.0
(API 级别 14)
Android 2.3
(API 级别 9)
Android 2.2
(API 级别 8)
Android 1.5
(API 级别 3)
TYPE_ACCELEROMETER
TYPE_AMBIENT_TEMPERATURE 可用 不可用 不可用 不适用
TYPE_GRAVITY 可用 不可用 不适用
TYPE_GYROSCOPE 可用 不可用1 不可用1
TYPE_LIGHT
TYPE_LINEAR_ACCELERATION 可用 不可用 不适用
TYPE_MAGNETIC_FIELD
TYPE_ORIENTATION 可用2 可用2 可用2 可用
TYPE_PRESSURE 可用 不可用1 不可用1
TYPE_PROXIMITY
TYPE_RELATIVE_HUMIDITY 可用 不可用 不可用 不适用
TYPE_ROTATION_VECTOR 可用 不可用 不适用
TYPE_TEMPERATURE 可用2 可用

1 此传感器类型是在 Android 1.5(API 级别)中添加的 3)、 但直到 Android 2.3(API 级别 9)才可供使用。

2 此传感器可用,但已 已弃用。

识别传感器和传感器特性

Android 传感器框架提供了多种方法,可以让您轻松确定 运行时。API 还提供了一些方法,让您能够确定 每个传感器的功能,例如最大范围、分辨率和功率 要求。

要识别设备上的传感器,您首先需要获取对传感器的引用 服务。为此,您可以通过以下方法创建 SensorManager 类的实例: 调用 getSystemService() 方法并传递 。SENSOR_SERVICE例如:

Kotlin

private lateinit var sensorManager: SensorManager
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager

Java

private SensorManager sensorManager;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);

接下来,您可以调用 getSensorList() 方法并使用 TYPE_ALL 常量。例如:

Kotlin

val deviceSensors: List<Sensor> = sensorManager.getSensorList(Sensor.TYPE_ALL)

Java

List<Sensor> deviceSensors = sensorManager.getSensorList(Sensor.TYPE_ALL);

如果您想列出给定类型的所有传感器,可以使用另一个常量来代替 TYPE_ALL,例如 TYPE_GYROSCOPETYPE_LINEAR_ACCELERATIONTYPE_GRAVITY

您还可以使用 getDefaultSensor() 方法并传入类型来确定设备上是否存在特定类型的传感器 常量。如果设备有多个特定类型的传感器,则 必须指定为默认传感器。如果指定传感器不存在默认传感器, 某种类型的传感器,该方法调用会返回 null,这意味着设备没有该类型的 传感器。例如,以下代码会检查设备上是否有磁力计:

Kotlin

private lateinit var sensorManager: SensorManager
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
if (sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null) {
    // Success! There's a magnetometer.
} else {
    // Failure! No magnetometer.
}

Java

private SensorManager sensorManager;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
if (sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null){
    // Success! There's a magnetometer.
} else {
    // Failure! No magnetometer.
}

注意:Android 不要求设备制造商构建任何 特定类型的传感器集成到他们的 Android 设备中,因此设备可以具有多种多样的 传感器配置。

除了列出设备上的传感器外,您还可以使用 Sensor 类来确定各个应用的 传感器。如果您希望应用根据哪些传感器或 传感器功能。例如,您可以使用 getResolution()getMaximumRange() 方法获取传感器的分辨率和最大测量范围。您还可以使用 getPower() 方法获取传感器的功率要求。

其中的两种公开方法特别适合您希望针对 不同制造商的传感器或不同版本的传感器。例如,如果您的应用 需要监控用户手势(如倾斜和摇晃),那么您可以创建一组数据过滤 具有特定供应商重力传感器和其他 一组数据过滤规则和优化措施,适用于没有重力传感器且 一个加速度计。以下代码示例展示了如何使用 getVendor()getVersion() 方法来执行 这个。在本示例中,我们要寻找一个将供应商列为 Google LLC 的重力传感器, 版本号为 3如果设备上没有该传感器,我们会尝试使用 加速度计。

Kotlin

private lateinit var sensorManager: SensorManager
private var mSensor: Sensor? = null

...

sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager

if (sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY) != null) {
    val gravSensors: List<Sensor> = sensorManager.getSensorList(Sensor.TYPE_GRAVITY)
    // Use the version 3 gravity sensor.
    mSensor = gravSensors.firstOrNull { it.vendor.contains("Google LLC") && it.version == 3 }
}
if (mSensor == null) {
    // Use the accelerometer.
    mSensor = if (sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null) {
        sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
    } else {
        // Sorry, there are no accelerometers on your device.
        // You can't play this game.
        null
    }
}

Java

private SensorManager sensorManager;
private Sensor mSensor;

...

sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSensor = null;

if (sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY) != null){
    List<Sensor> gravSensors = sensorManager.getSensorList(Sensor.TYPE_GRAVITY);
    for(int i=0; i<gravSensors.size(); i++) {
        if ((gravSensors.get(i).getVendor().contains("Google LLC")) &&
           (gravSensors.get(i).getVersion() == 3)){
            // Use the version 3 gravity sensor.
            mSensor = gravSensors.get(i);
        }
    }
}
if (mSensor == null){
    // Use the accelerometer.
    if (sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null){
        mSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    } else{
        // Sorry, there are no accelerometers on your device.
        // You can't play this game.
    }
}

另一个有用的方法是 getMinDelay() 方法。 该函数会返回传感器可用于感应数据的最小时间间隔(以微秒为单位)。任何传感器 会返回 getMinDelay() 的非零值 是流式传输 传感器。流式传感器定期感知数据,在 Android 2.3 (API) 中引入 9 级)。如果传感器在您调用 getMinDelay() 方法时返回零,则表示 传感器不是流式传感器,因为它仅在 参数。

getMinDelay() 方法非常有用,因为它 您可以决定 传感器用来获取数据如果应用中的某些功能需要大量流量 捕获率或流式传感器,则可以使用此方法来确定 满足这些要求,然后启用或停用应用中的相关功能 。

注意:并非传感器的最大数据采集速率 必须是传感器框架向应用传送传感器数据的速率。通过 传感器框架通过传感器事件报告数据,而几个因素会影响 您的应用将收到传感器事件。如需了解详情,请参阅监控传感器事件

监控传感器事件

要监控原始传感器数据,您需要实现通过 SensorEventListener 接口:onAccuracyChanged()onSensorChanged()。Android 系统调用 这些方法:

以下代码展示了如何使用 onSensorChanged() 方法监控 光传感器此示例在 TextView 中显示原始传感器数据 即 在 main.xml 文件中定义为 sensor_data

Kotlin

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

    public override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main)

        sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
        mLight = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT)
    }

    override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {
        // Do something here if sensor accuracy changes.
    }

    override fun onSensorChanged(event: SensorEvent) {
        // The light sensor returns a single value.
        // Many sensors return 3 values, one for each axis.
        val lux = event.values[0]
        // Do something with this sensor value.
    }

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

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

Java

public class SensorActivity extends Activity implements SensorEventListener {
    private SensorManager sensorManager;
    private Sensor mLight;

    @Override
    public final void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        mLight = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
    }

    @Override
    public final void onAccuracyChanged(Sensor sensor, int accuracy) {
        // Do something here if sensor accuracy changes.
    }

    @Override
    public final void onSensorChanged(SensorEvent event) {
        // The light sensor returns a single value.
        // Many sensors return 3 values, one for each axis.
        float lux = event.values[0];
        // Do something with this sensor value.
    }

    @Override
    protected void onResume() {
        super.onResume();
        sensorManager.registerListener(this, mLight, SensorManager.SENSOR_DELAY_NORMAL);
    }

    @Override
    protected void onPause() {
        super.onPause();
        sensorManager.unregisterListener(this);
    }
}

在本示例中,在调用 registerListener() 方法时指定了默认数据延迟 (SENSOR_DELAY_NORMAL)。数据 延迟(也称作采样率)控制传感器事件发送到应用的时间间隔 onSensorChanged() 回调方法,默认 数据延迟适用于 典型的屏幕方向变化,并使用 200,000 微秒的延迟。您可以指定其他 数据延迟,例如 SENSOR_DELAY_GAME(20,000 微秒) 延迟)、SENSOR_DELAY_UI(延迟 60,000 微秒)或 SENSOR_DELAY_FASTEST(延迟 0 微秒)。从 Android 3.0 (API 级别 11),您还可以将延迟时间指定为绝对值(以微秒为单位)。

您指定的延迟只是建议的延迟。Android 系统和其他应用 改变这种延迟最佳做法是指定尽可能长的延迟时间,因为 通常,系统使用的延迟时间会比您指定的延迟时间短(也就是说,您应该选择 但仍能满足应用需求的最低采样率)。使用较长的延迟时间会导致 可以降低处理器上的负载,从而降低功耗。

没有公共方法可以确定传感器框架的发送速率 将传感器事件发送到您的应用不过,您可以使用与每个 传感器事件计算多个事件的采样率。您不必更改 采样率(延迟)的值。如果出于某种原因,您确实需要更改延迟时间, 必须取消注册,然后重新注册传感器监听器。

另外还需要注意的是,此示例使用 onResume(), 用于注册和取消注册传感器事件的 onPause() 回调方法 监听器。最佳做法是始终停用不需要的传感器,尤其是在 活动已暂停。否则,可能几个小时后就会耗尽电池电量,因为某些传感器 具有很高的功耗要求,并且可能会很快耗尽电池电量。系统 在屏幕关闭时不会自动停用传感器。

处理不同的传感器配置

Android 没有为设备指定标准的传感器配置 这意味着设备制造商可以将他们需要的任何传感器配置纳入其 采用 Android 的手机。因此,设备可能会包含多种 各种传感器。 如果您的应用依赖于特定类型的传感器,则必须确保 传感器,以便您的应用可以成功运行。

有两种方法可以确保设备上存在特定的传感器:

  • 在运行时检测传感器,并根据需要启用或停用应用功能。
  • 使用 Google Play 过滤器定位具有特定传感器配置的设备。

下面将分别讨论这两种方法。

在运行时检测传感器

如果您的应用使用特定类型的传感器,但不依赖于它,您可以使用 传感器框架在运行时检测传感器,然后停用或启用应用功能 视情况而定。例如,导航应用可以使用温度传感器, 压力传感器、GPS 传感器和地磁场传感器,用于显示温度、气压 压力、位置和罗盘方位。如果设备没有压力传感器,您可以使用 传感器框架在运行时检测压力传感器的缺失,然后停用 显示压力的部分。例如,以下代码会检查 设备上是否有压力传感器:

Kotlin

private lateinit var sensorManager: SensorManager
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager

if (sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE) != null) {
    // Success! There's a pressure sensor.
} else {
    // Failure! No pressure sensor.
}

Java

private SensorManager sensorManager;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
if (sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE) != null){
    // Success! There's a pressure sensor.
} else {
    // Failure! No pressure sensor.
}

使用 Google Play 过滤器定位特定的传感器配置

如果您要在 Google Play 上发布应用,可以使用 <uses-feature> 元素,用于从符合以下条件的设备中滤除您的应用: 具有适合您应用的传感器配置。通过 <uses-feature> 元素具有多个硬件描述符,可用于过滤 根据是否存在特定传感器来调整应用。您可以列出的传感器包括: 加速度计、气压计、罗盘(地磁场)、陀螺仪、光和近程。通过 以下是一个清单条目示例,它过滤没有加速度计的应用:

<uses-feature android:name="android.hardware.sensor.accelerometer"
              android:required="true" />

如果您将此元素和描述符添加到应用的清单中,用户将看到 应用在 Google Play 上架。

只有在您的应用需要的情况下,您才能将描述符设置为 android:required="true"。 完全依靠特定的传感器。如果您的应用使用传感器来实现某些功能,但 仍然在没有传感器的情况下运行,则应在 <uses-feature> 中列出该传感器 但要将描述符设置为 android:required="false"。这有助于确保 即使设备没有该传感器,也可以安装您的应用。这也是一个 可帮助您跟踪应用所使用功能的项目管理最佳实践。 请注意,如果您的应用使用特定的传感器,但在没有传感器的情况下仍会运行, 则您应在运行时检测传感器,并像之前一样停用或启用应用功能 适当的选择。

传感器坐标系

通常,传感器框架使用标准的 3 轴坐标系来表示数据值。 对于大多数传感器,在设备运行时,以设备屏幕为参照物定义坐标系 保持其默认方向(参见图 1)。当设备处于默认屏幕方向时, X 轴水平指向右侧,Y 轴垂直指向上方,Z 轴为垂直方向 轴指向屏幕外侧。在此系统中,屏幕背后的坐标 Z 值为负。以下传感器使用此坐标系:

图 1. 传感器使用的坐标系(相对于设备) API。

关于这个坐标系,最重要的是需要了解:轴并不是 在设备的屏幕方向(即传感器的坐标系)发生变化时交换 绝不会随着设备的移动而变化。此行为与 OpenGL 坐标系

还需要注意一点是,您的应用不能假定设备的自然 (默认)屏幕方向为纵向。许多平板设备的自然屏幕方向为横屏。且 传感器坐标系始终以设备的自然屏幕方向为基础。

最后,如果您的应用将传感器数据与屏幕显示相匹配,您需要使用 getRotation() 方法确定屏幕旋转角度,然后使用 要映射的 remapCoordinateSystem() 方法 将传感器坐标映射到屏幕坐标。即使您的清单指定了 仅限纵向显示

注意:某些传感器和方法使用的坐标系 相对于世界参照系(而不是设备的参照系)。这些 传感器和方法返回的数据表示设备相对于 地球。如需了解详情,请参阅 getOrientation() 方法、getRotationMatrix() 方法、屏幕方向 传感器旋转矢量 传感器

传感器速率限制

为了保护有关用户的潜在敏感信息(如果您的应用以 Android 12(API 级别 31)或更高版本,则系统会对刷新施加限制 特定移动传感器和位置传感器的数据速率。这些数据 包含由设备的 加速度计陀螺仪地磁场 传感器

刷新率限制取决于您访问传感器数据的方式:

如果您的应用需要以更高的速率收集移动传感器数据,则必须 声明 HIGH_SAMPLING_RATE_SENSORS 权限,如以下代码段所示。否则,如果您的应用尝试 在不声明此权限的情况下以更高的速率收集移动传感器数据, 会发生 SecurityException

AndroidManifest.xml

<manifest ...>
    <uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS"/>
    <application ...>
        ...
    </application>
</manifest>

访问和使用传感器的最佳做法

在设计传感器实现时,请务必遵循 部分。这些准则是推荐采用的最佳实践,适用于所有传感器使用者 框架来访问传感器并获取传感器数据。

仅在前台采集传感器数据

在搭载 Android 9(API 级别 28)或更高版本的设备上,在 具有下列限制:

鉴于这些限制,最好在 应用在前台运行或作为应用的一部分运行 前台服务

取消注册传感器监听器

使用完传感器或在传感器使用完毕后,请务必取消注册传感器的监听器 活动暂停。如果注册了传感器监听器且其 activity 已暂停,则传感器将 继续获取数据并使用电池资源,除非您取消注册传感器。以下 代码展示了如何使用 onPause() 方法取消注册监听器:

Kotlin

private lateinit var sensorManager: SensorManager
...
override fun onPause() {
    super.onPause()
    sensorManager.unregisterListener(this)
}

Java

private SensorManager sensorManager;
...
@Override
protected void onPause() {
    super.onPause();
    sensorManager.unregisterListener(this);
}

如需了解详情,请参阅 unregisterListener(SensorEventListener)

使用 Android 模拟器进行测试

Android Emulator 包含一组虚拟传感器控件, 您可以测试加速度计、环境温度计、磁力计等传感器, 例如近距离、光照等

模拟器与运行 SdkController 传感器 应用。请注意,此应用仅适用于运行 Android 4.0 (API 级别 14)或更高版本。(如果设备运行的是 Android 4.0,它必须 已安装修订版 2。)SdkControllerSensor 应用会监控 设备上的传感器并将其传输到模拟器。模拟器是 然后根据从 。

您可以在 以下位置:

$ your-android-sdk-directory/tools/apps/SdkController

如需在设备和模拟器之间传输数据,请按照以下说明操作 步骤:

  1. 检查 USB 调试
  2. 使用 USB 数据线将设备连接到开发计算机。
  3. 在设备上启动 SdkControllerSensor 应用。
  4. 在应用中,选择您要模拟的传感器。
  5. 运行以下 adb 命令:

  6. $ adb forward tcp:1968 tcp:1968
    
  7. 启动模拟器。现在,您应该能够将转换应用于 来移动模拟器。

注意 :如果您对画面的移动 实体设备未对模拟器进行转换,请尝试运行 adb 命令。

有关详情,请参阅 Android 模拟器指南

请勿阻塞 onSensorChanged() 方法

传感器数据可以以很高的频率变化,这意味着系统可能会频繁调用 onSensorChanged(SensorEvent) 方法。最佳做法是 应在 onSensorChanged(SensorEvent) 方法中执行尽可能少的操作,以免阻塞它。如果您的 应用要求您对传感器数据进行任何数据过滤或减少操作,则应执行 在 onSensorChanged(SensorEvent) 方法之外运行的应用。

避免使用已弃用的方法或传感器类型

一些方法和常量已弃用。 具体而言,TYPE_ORIENTATION 传感器类型已弃用。应改用 getOrientation() 方法来获取屏幕方向数据。同样, 已废弃 TYPE_TEMPERATURE 传感器类型。您应该使用 改为在设备上使用 TYPE_AMBIENT_TEMPERATURE 传感器类型 运行 Android 4.0 的设备

使用传感器之前应先进行验证

在尝试从传感器采集数据之前,应始终先验证设备上是否存在该传感器。错误做法 我们假设某个传感器的存在只是因为它是一个经常使用的传感器。设备制造商 不需要在其设备中提供任何特定的传感器。

谨慎选择传感器延迟

使用 registerListener() 方法注册传感器时,请务必选择适合您 应用或用例。传感器能以非常高的频率提供数据。允许系统发送 您不需要的额外数据会浪费系统资源和消耗电池电量。