访问设备传感器

Browse sample. 浏览示例

设备具有各种可用的传感器。 一些传感器可以检测运动,其他传感器可以检测环境中的变化,例如光线。 对这些传感器的监控和响应使应用能够动态地适应设备被使用的方式。 你还可以响应传感器的变化,并向用户发出警报。 本文简要概述了 .NET Multi-platform App UI (.NET MAUI) 支持的常见传感器。

Microsoft.Maui.Devices.Sensors 命名空间中提供了与设备传感器相关的类型。

传感器速度

传感器速度将设置传感器向应用返回数据的速度。 启动传感器时,你可以通过 SensorSpeed 枚举提供所需的传感器速度:

  • Fastest
    尽可能快地获取传感器数据(不保证在 UI 线程上返回)。

  • Game
    适合游戏的速率(不保证在 UI 线程上返回)。

  • UI
    适合一般用户界面的速率。

  • Default
    适合屏幕方向更改的默认速率。

警告

同时监控太多传感器可能会影响传感器数据返回到应用的速度。

在 .NET 8 中,SensorSpeed 间隔在所有平台上都是相同的:

  • Default 使用 200 毫秒的间隔。
  • UI 使用 60 毫秒的间隔。
  • Game 使用 20 毫秒的间隔。
  • Fastest 使用 5 毫秒的间隔。

传感器事件处理程序

添加到具有 GameFastest 速度的传感器的事件处理程序不能保证在 UI 线程上运行。 如果事件处理程序需要访问用户界面元素,则必须使用 MainThread.BeginInvokeOnMainThread 方法在 UI 线程上运行该代码。

加速计

加速计传感器可测量设备沿其三个轴的加速度。 传感器报告的数据表示用户如何移动装置。

通过 IAccelerometer 接口可以访问传感器,可通过 Accelerometer.Default 属性提供。 IAccelerometer 接口和 Accelerometer 类都包含在 Microsoft.Maui.Devices.Sensors 命名空间中。

开始使用

要访问加速计功能,可能需要以下特定于平台的设置:

如果应用以 Android 12+ (API 31+) 为目标,则系统会对来自该传感器的数据的刷新率设置 200 Hz 的限制。 如果应用需要使用 Fastest 传感器速度收集传感器数据,则必须声明 HIGH_SAMPLING_RATE_SENSORS 权限。 可通过以下方式配置权限:

  • 添加基于程序集的权限:

    打开 Platforms/Android/MainApplication.cs 文件,并在 using 指令后添加以下程序集特性:

    [assembly: UsesPermission(Android.Manifest.Permission.HighSamplingRateSensors)]
    

    - 或 -

  • 更新 Android 清单:

    打开 Platforms/Android/AndroidManifest.xml 文件,并在 manifest 节点中添加以下行:

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

    - 或 -

  • 在清单编辑器中更新 Android 清单:

    在 Visual Studio 中,双击 Platforms/Android/AndroidManifest.xml 文件以打开 Android 清单编辑器。 然后,在“所需权限”下,选中“HIGH_SAMPLING_RATE_SENSORS”权限。 这样会自动更新 AndroidManifest.xml 文件。

注意

如果用户使用“设备切换”关闭麦克风访问权限,则无论是否声明 HIGH_SAMPLING_RATE_SENSORS 权限,运动和位置传感器的速率将始终受到限制。

监控加速计传感器

要开始监控加速计传感器,应调用 IAccelerometer.Start 方法。 .NET MAUI 通过引发 IAccelerometer.ReadingChanged 事件将加速计数据更改发送到应用。 使用 IAccelerometer.Stop 方法停止监控传感器。 可以使用 IAccelerometer.IsMonitoring 属性检测加速计的监控状态,如果加速计已启动且目前正在被监控,则将为 true

下面的代码示例演示如何监控加速计的变化:

public void ToggleAccelerometer()
{
    if (Accelerometer.Default.IsSupported)
    {
        if (!Accelerometer.Default.IsMonitoring)
        {
            // Turn on accelerometer
            Accelerometer.Default.ReadingChanged += Accelerometer_ReadingChanged;
            Accelerometer.Default.Start(SensorSpeed.UI);
        }
        else
        {
            // Turn off accelerometer
            Accelerometer.Default.Stop();
            Accelerometer.Default.ReadingChanged -= Accelerometer_ReadingChanged;
        }
    }    
}

private void Accelerometer_ReadingChanged(object sender, AccelerometerChangedEventArgs e)
{
    // Update UI Label with accelerometer state
    AccelLabel.TextColor = Colors.Green;
    AccelLabel.Text = $"Accel: {e.Reading}";
}

加速计读数以 G 为单位反馈回来。G 是重力单位,等于地球引力场施加的重力 $(9.81 m/s^2)$。

坐标系是相对于设备屏幕的默认方向定义的。 设备的屏幕方向更改时,轴不会交换。

X 轴水平向右,Y 轴垂直向上,Z 轴从屏幕正面指向外。 在此坐标系中,屏幕后方的坐标具有负 Z 值。

示例:

  • 当设备平放在桌面上,并从左侧向右推时,X 轴加速值为正。

  • 设备平放在桌面上时,加速度值为 +1.00 G 或 $(+9.81m/s^2)$,相当于设备的加速度 $(0 m/s^2)$ 减去重力 $(-9.81m/s^2)$,并以 G 为规范。

  • 设备平放在桌面上,以 A $m/s^2$ 的加速度向上推时,加速度值等于 $A+9.81$,相当于设备的加速度 $(+A m/s^2)$ 减去重力 $(-9.81 m/s^2)$,并以 G 为规范。

平台特定信息(加速计)

不存在与加速计传感器相关的特定于平台的信息。

Barometer

气压计传感器将测量环境空气压力。 传感器报告的数据代表当前气压。 数据会在第一次开始监控传感器时报告,然后在每次压力变化时报告。

通过 IBarometer 接口可以访问传感器,可通过 Barometer.Default 属性提供。 IBarometer 接口和 Barometer 类都包含在 Microsoft.Maui.Devices.Sensors 命名空间中。

要开始监控气压计传感器,应调用 IBarometer.Start 方法。 .NET MAUI 通过引发 IBarometer.ReadingChanged 事件将气压读数发送到应用。 使用 IBarometer.Stop 方法停止监控传感器。 可以使用 IBarometer.IsMonitoring 属性检测晴雨表的监控状态,如果晴雨表目前正在被监控,则将为 true

压力读数以百帕表示。

以下代码示例展示如何监控晴雨表的变化:

public void ToggleBarometer()
{
    if (Barometer.Default.IsSupported)
    {
        if (!Barometer.Default.IsMonitoring)
        {
            // Turn on barometer
            Barometer.Default.ReadingChanged += Barometer_ReadingChanged;
            Barometer.Default.Start(SensorSpeed.UI);
        }
        else
        {
            // Turn off barometer
            Barometer.Default.Stop();
            Barometer.Default.ReadingChanged -= Barometer_ReadingChanged;
        }
    }
}

private void Barometer_ReadingChanged(object sender, BarometerChangedEventArgs e)
{
    // Update UI Label with barometer state
    BarometerLabel.TextColor = Colors.Green;
    BarometerLabel.Text = $"Barometer: {e.Reading}";
}

特定于平台的信息(晴雨表)

本部分介绍与晴雨表传感器相关的特定于平台的实现详细信息。

无特定于平台的实现细节。

Compass

指南针传感器监测设备的磁北方向。

通过 ICompass 接口可以访问传感器,可通过 Compass.Default 属性提供。 ICompass 接口和 Compass 类都包含在 Microsoft.Maui.Devices.Sensors 命名空间中。

若要开始监控指南针传感器,请调用 ICompass.Start 方法。 当指南针方向改变时,.NET MAUI 会引发 ICompass.ReadingChanged 事件。 使用 ICompass.Stop 方法停止监控传感器。 可以使用 ICompass.IsMonitoring 属性检测指南针的监控状态,如果指南针当前正受到监控,则该属性将为 true

以下代码示例演示如何监控指南针的变化:

private void ToggleCompass()
{
    if (Compass.Default.IsSupported)
    {
        if (!Compass.Default.IsMonitoring)
        {
            // Turn on compass
            Compass.Default.ReadingChanged += Compass_ReadingChanged;
            Compass.Default.Start(SensorSpeed.UI);
        }
        else
        {
            // Turn off compass
            Compass.Default.Stop();
            Compass.Default.ReadingChanged -= Compass_ReadingChanged;
        }
    }
}

private void Compass_ReadingChanged(object sender, CompassChangedEventArgs e)
{
    // Update UI Label with compass state
    CompassLabel.TextColor = Colors.Green;
    CompassLabel.Text = $"Compass: {e.Reading}";
}

特定于平台的信息(指南针)

本部分介绍与指南针功能相关的特定于平台的实现详细信息。

Android 不提供用于检索指南针航向的 API。 .NET MAUI 使用 Google 推荐的方法,利用加速计和磁力计传感器来计算磁北航向。

在极少数情况下,可能会看到不一致的结果,因为需要校准传感器。 在 Android 上,指南针的重新校准因手机型号和 Android 版本而异。 需要在 Internet 上搜索如何重新校准指南针。 下面是有助于重新校准指南针的两个链接:

使用应用同时运行多个传感器可能会影响传感器速度。

低通滤波器

根据 Android 指南针值的更新和计算方式,可能需要平滑处理这些值。 可以应用一个低通滤波器平均角度的正弦和余弦值,并且可以使用接受 bool applyLowPassFilter 参数的 Start 方法重载启用此滤波器:

Compass.Default.Start(SensorSpeed.UI, applyLowPassFilter: true);

这仅适用于 Android 平台,iOS 和 Windows 会忽略该参数。 有关详细信息,请参阅此 GitHub 问题注释

摇动

尽管本文将摇动列为传感器,但它不是。 加速计用于检测设备何时摇动。

通过 IAccelerometer 接口可以访问传感器,可通过 Accelerometer.Default 属性提供。 IAccelerometer 接口和 Accelerometer 类都包含在 Microsoft.Maui.Devices.Sensors 命名空间中。

注意

如果你的应用需要使用 Fastest 传感器速度采集加速计传感器数据 ,则必须声明 HIGH_SAMPLING_RATE_SENSORS 权限。 有关详细信息,请参阅加速计

检测抖动 API 使用来自加速计的原始读数来计算加速度。 它使用一种简单的队列机制来检测最近加速计事件的 75% 是否发生在最后半秒。 通过将加速计的 X、Y 和 Z 读数的平方相加 ($x^2+y^2+z^2$),并将其与特定的阈值进行比较计算加速度。

要开始监控加速计传感器,应调用 IAccelerometer.Start 方法。 检测到摇动时,将引发 IAccelerometer.ShakeDetected 事件。 使用 IAccelerometer.Stop 方法停止监控传感器。 可以使用 IAccelerometer.IsMonitoring 属性检测加速计的监控状态,如果加速计已启动且目前正在被监控,则将为 true

建议对 SensorSpeed 使用 Game 或更快的速度。

以下代码示例展示如何监控 ShakeDetected 事件的加速计:

private void ToggleShake()
{
    if (Accelerometer.Default.IsSupported)
    {
        if (!Accelerometer.Default.IsMonitoring)
        {
            // Turn on accelerometer
            Accelerometer.Default.ShakeDetected += Accelerometer_ShakeDetected;
            Accelerometer.Default.Start(SensorSpeed.Game);
        }
        else
        {
            // Turn off accelerometer
            Accelerometer.Default.Stop();
            Accelerometer.Default.ShakeDetected -= Accelerometer_ShakeDetected;
        }
    }
}

private void Accelerometer_ShakeDetected(object sender, EventArgs e)
{
    // Update UI Label with a "shaked detected" notice, in a randomized color
    ShakeLabel.TextColor = new Color(Random.Shared.Next(256), Random.Shared.Next(256), Random.Shared.Next(256));
    ShakeLabel.Text = $"Shake detected";
}

特定于平台的信息(摇动)

不存在与加速计传感器相关的特定于平台的信息。

陀螺仪

陀螺仪传感器测量围绕设备三个主轴旋转的角速度。

通过 IGyroscope 接口可以访问传感器,可通过 Gyroscope.Default 属性提供。 IGyroscope 接口和 Gyroscope 类都包含在 Microsoft.Maui.Devices.Sensors 命名空间中。

开始使用

若要访问陀螺仪功能,可能需要以下特定于平台的设置:

如果应用以 Android 12+ (API 31+) 为目标,则系统会对来自该传感器的数据的刷新率设置 200 Hz 的限制。 如果应用需要使用 Fastest 传感器速度收集传感器数据,则必须声明 HIGH_SAMPLING_RATE_SENSORS 权限。 可通过以下方式配置权限:

  • 添加基于程序集的权限:

    打开 Platforms/Android/MainApplication.cs 文件,并在 using 指令后添加以下程序集特性:

    [assembly: UsesPermission(Android.Manifest.Permission.HighSamplingRateSensors)]
    

    - 或 -

  • 更新 Android 清单:

    打开 Platforms/Android/AndroidManifest.xml 文件,并在 manifest 节点中添加以下行:

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

    - 或 -

  • 在清单编辑器中更新 Android 清单:

    在 Visual Studio 中,双击 Platforms/Android/AndroidManifest.xml 文件以打开 Android 清单编辑器。 然后,在“所需权限”下,选中“HIGH_SAMPLING_RATE_SENSORS”权限。 这样会自动更新 AndroidManifest.xml 文件。

注意

如果用户使用“设备切换”关闭麦克风访问权限,则无论是否声明 HIGH_SAMPLING_RATE_SENSORS 权限,运动和位置传感器的速率将始终受到限制。

监控陀螺仪传感器

若要开始监控陀螺仪传感器,请调用 IGyroscope.Start 方法。 .NET MAUI 通过引发 IGyroscope.ReadingChanged 事件向应用发送陀螺仪数据变更。 此事件提供的数据以 rad/s (每秒弧度)度量。 使用 IGyroscope.Stop 方法停止监控传感器。 可以使用 IGyroscope.IsMonitoring 属性检测陀螺仪的监控状态,如果陀螺仪已启动且目前正在被监控,则将为 true

下面的代码示例展示如何监控陀螺仪:

private void ToggleGyroscope()
{
    if (Gyroscope.Default.IsSupported)
    {
        if (!Gyroscope.Default.IsMonitoring)
        {
            // Turn on gyroscope
            Gyroscope.Default.ReadingChanged += Gyroscope_ReadingChanged;
            Gyroscope.Default.Start(SensorSpeed.UI);
        }
        else
        {
            // Turn off gyroscope
            Gyroscope.Default.Stop();
            Gyroscope.Default.ReadingChanged -= Gyroscope_ReadingChanged;
        }
    }
}

private void Gyroscope_ReadingChanged(object sender, GyroscopeChangedEventArgs e)
{
    // Update UI Label with gyroscope state
    GyroscopeLabel.TextColor = Colors.Green;
    GyroscopeLabel.Text = $"Gyroscope: {e.Reading}";
}

特定于平台的信息(陀螺仪)

没有与陀螺仪传感器相关的特定于平台的信息。

磁力仪

磁力计传感器指示设备相对于地球磁场的方向。

通过 IMagnetometer 接口可以访问传感器,可通过 Magnetometer.Default 属性提供。 IMagnetometer 接口和 Magnetometer 类都包含在 Microsoft.Maui.Devices.Sensors 命名空间中。

开始使用

要访问磁力计功能,可能需要以下特定于平台的设置:

如果应用以 Android 12+ (API 31+) 为目标,则系统会对来自该传感器的数据的刷新率设置 200 Hz 的限制。 如果应用需要使用 Fastest 传感器速度收集传感器数据,则必须声明 HIGH_SAMPLING_RATE_SENSORS 权限。 可通过以下方式配置权限:

  • 添加基于程序集的权限:

    打开 Platforms/Android/MainApplication.cs 文件,并在 using 指令后添加以下程序集特性:

    [assembly: UsesPermission(Android.Manifest.Permission.HighSamplingRateSensors)]
    

    - 或 -

  • 更新 Android 清单:

    打开 Platforms/Android/AndroidManifest.xml 文件,并在 manifest 节点中添加以下行:

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

    - 或 -

  • 在清单编辑器中更新 Android 清单:

    在 Visual Studio 中,双击 Platforms/Android/AndroidManifest.xml 文件以打开 Android 清单编辑器。 然后,在“所需权限”下,选中“HIGH_SAMPLING_RATE_SENSORS”权限。 这样会自动更新 AndroidManifest.xml 文件。

注意

如果用户使用“设备切换”关闭麦克风访问权限,则无论是否声明 HIGH_SAMPLING_RATE_SENSORS 权限,运动和位置传感器的速率将始终受到限制。

监控磁力计传感器

若要开始监控磁力计传感器,请调用 IMagnetometer.Start 方法。 .NET MAUI 通过引发 IMagnetometer.ReadingChanged 事件向应用发送磁力计数据变更。 此事件提供的数据以 $μT$ (特斯拉)为单位。 使用 IMagnetometer.Stop 方法停止监控传感器。 可以使用 IMagnetometer.IsMonitoring 属性检测磁力计的监控状态,如果磁力计已启动且目前正在被监控,则将为 true

以下代码示例展示如何监控磁力计:

private void ToggleMagnetometer()
{
    if (Magnetometer.Default.IsSupported)
    {
        if (!Magnetometer.Default.IsMonitoring)
        {
            // Turn on magnetometer
            Magnetometer.Default.ReadingChanged += Magnetometer_ReadingChanged;
            Magnetometer.Default.Start(SensorSpeed.UI);
        }
        else
        {
            // Turn off magnetometer
            Magnetometer.Default.Stop();
            Magnetometer.Default.ReadingChanged -= Magnetometer_ReadingChanged;
        }
    }
}

private void Magnetometer_ReadingChanged(object sender, MagnetometerChangedEventArgs e)
{
    // Update UI Label with magnetometer state
    MagnetometerLabel.TextColor = Colors.Green;
    MagnetometerLabel.Text = $"Magnetometer: {e.Reading}";
}

特定于平台的信息(磁力计)

没有与磁力计传感器相关的特定于平台的信息。

方向

方向传感器监控设备在三维空间中的方向。

注意

此传感器不用于确定设备的视频显示是否处于纵向或横向模式。 改用 DeviceDisplay.Current.MainDisplayInfo.Orientation 属性。 有关详细信息,请参阅设备显示信息

通过 IOrientationSensor 接口可以访问传感器,可通过 OrientationSensor.Default 属性提供。 IOrientationSensor 接口和 OrientationSensor 类都包含在 Microsoft.Maui.Devices.Sensors 命名空间中。

若要开始监控方向传感器,请调用 IOrientationSensor.Start 方法。 .NET MAUI 通过引发 IOrientationSensor.ReadingChanged 事件向应用发送方向数据变更。 使用 IOrientationSensor.Stop 方法停止监控传感器。 可以使用 IOrientationSensor.IsMonitoring 属性检测方向的监控状态,如果方向已启动且目前正在被监控,则将为 true

以下代码示例展示如何监控方向传感器:

private void ToggleOrientation()
{
    if (OrientationSensor.Default.IsSupported)
    {
        if (!OrientationSensor.Default.IsMonitoring)
        {
            // Turn on orientation
            OrientationSensor.Default.ReadingChanged += Orientation_ReadingChanged;
            OrientationSensor.Default.Start(SensorSpeed.UI);
        }
        else
        {
            // Turn off orientation
            OrientationSensor.Default.Stop();
            OrientationSensor.Default.ReadingChanged -= Orientation_ReadingChanged;
        }
    }
}

private void Orientation_ReadingChanged(object sender, OrientationSensorChangedEventArgs e)
{
    // Update UI Label with orientation state
    OrientationLabel.TextColor = Colors.Green;
    OrientationLabel.Text = $"Orientation: {e.Reading}";
}

IOrientationSensor 读数以 Quaternion 的形式返回报告,描述了设备基于两个三维坐标系的方向:

设备(通常为手机或平板电脑)的三维坐标系具有以下轴:

  • 在纵向模式下,正 X 轴指向显示器右侧。
  • 在纵向模式下,正 Y 轴指向设备的顶部。
  • 正 Z 轴指向屏幕外侧。

地球的三维坐标系具有以下轴:

  • 正 X 轴与地球表面相切,指向东方。
  • 正 Y 轴也与地球表面相切,指向北方。
  • 正 Z 轴垂直于地球表面,指向上方。

Quaternion 描述了设备坐标系相对于地球坐标系的旋转。

Quaternion 值与绕轴旋转密切相关。 如果旋转轴是规范化矢量 ($a_x, a_y, a_z$),并且旋转角度为 $\theta$,则四元数的 (X, Y, Z, W) 分量是:

$(a_x \times \sin(\theta/2), a_y \times \sin(\theta/2), a_z \times \sin(\theta/2), \cos(\theta/2))$

这些是右手坐标系,因此右手的拇指指向旋转轴的正方向,手指弯曲表示正角的旋转方向。

示例:

  • 如果设备平躺在桌子上,使其屏幕面朝上,设备顶部(在纵向模式下)指向北边,则会对齐这两个坐标系。 Quaternion 值表示标识四元数 (0, 0, 0, 1)。 可以相对于此位置分析所有旋转。

  • 如果设备平躺在桌子上,使其屏幕面朝上,设备顶部(在纵向模式下)指向西边,则 Quaternion 值为 (0, 0, 0.707, 0.707)。 设备已绕地球的 Z 轴旋转 90 度。

  • 如果设备直立,设备顶部(在纵向模式下)指向天空,设备背面朝向北边,则设备已绕 X 轴旋转 90 度。 Quaternion 值为 (0.707, 0, 0, 0.707)。

  • 如果设备的左边缘在桌子上,顶部指向北边,则设备已绕 Y 轴旋转 -90 度(或绕 Y 轴负方向旋转 90 度)。 Quaternion 值为 (0, -0.707, 0, 0.707)。

特定于平台的信息(方向)

没有与方向传感器相关的特定于平台的信息。