【问题标题】:How to read Android Sensor data only once, when asked for如何在被要求时仅读取一次 Android Sensor 数据
【发布时间】:2021-08-31 14:23:44
【问题描述】:

我正在尝试读取 Java android 应用中的加速度计和/或地磁传感器,以确定设备在某一时刻的方向。但是传感器本身并不重要,我的问题可以应用于您想读取的任何类型的传感器,无论是运动、温度、光、压力等等。

我到处都可以看到用于设置来自传感器的数据“流”的代码,具有事件侦听器以及对传感器通过回调发送给您的数据进行“反应”的能力。

这不是我所追求的,我认为可能无法做到我想要的。

想要的是读取传感器数据一次。 不是两次,不是连续 3 秒,不是当传感器向我发送事件时。 开启、阅读、关闭。

当我要求阅读时,我只需要阅读。 当我得到那个读数后,我就不需要更多的读数了。

一旦你拥有足够的权限,比如anysensor.getCurrentState(),感觉应该是一个简单的单行操作。 但是从我可以阅读的内容来看,我只找到依赖于 sensorManager 事件侦听器的文档,并且必须设置整个类和 5 个不同的事件回调:

https://developer.android.com/guide/topics/sensors/sensors_position#sensors-pos-orient

我猜我可以做到这一点,并尝试使其尽可能轻,让 eventListeners 在第一次阅读时自动停止。但是对于我需要的东西来说,感觉很潮,而且代码很多。而且我正在尝试做一个非常简单的任务,阅读相关内容,并完成它,这将需要一些异步的东西。 所以我想我必须“暂停”应用程序,直到我得到第一个结果。

这实际上是最简单/唯一的方法吗?

【问题讨论】:

  • 该页面上的第一个示例有什么问题?
  • 这是一个异步设置,有 5 个事件监听器,两个函数组成两页代码。我的问题是“有没有办法在没有事件监听器的情况下只读取传感器数据一次”像sensor.getcurrentState() 之类的东西(我做了一个)。一行,可能是 5,而不是 100。我不需要任何异步的东西,我不需要来自传感器的连续数据。我以为我写的解释了这一点?
  • 如果除了必须进行完整设置之外别无他法,我也想知道。但理想情况下,我希望有一种更简单的方法来读取传感器一次。
  • 真的吗?您在该页面上看到的第一个示例可能就是您要查找的内容! private lateinit var sensorManager: SensorManager ... // Rotation matrix based on current readings from accelerometer and magnetometer. val rotationMatrix = FloatArray(9); SensorManager.getRotationMatrix(rotationMatrix, null, accelerometerReading, magnetometerReading); // Express the updated rotation matrix as three orientation angles. val orientationAngles = FloatArray(3); SensorManager.getOrientation(rotationMatrix, orientationAngles);
  • @AlbertoSinigaglia 谢谢你,对不起,我以为你在谈论另一段代码。但我认为它不起作用。也许我错了,但在他们的例子中,“...”会丢失一些代码。据我了解,您必须将来自传感器的数据作为参数提供给SensorManager.getRotationMatrix( (float[] R, float[] I, float[] gravity, float[] geomagnetic)(在他们的示例中为 accelerometerReadingmagnetometerReading)。但他们没有展示如何获取这些值,除了在 eventListeners 的示例中......

标签: java android android-studio sensors sensormanager


【解决方案1】:

从我在这里看到的内容来看,如果不设置 eventListeners,似乎无法读取传感器数据。

Android get sensor data without EventListeners

我还没有结束这个问题,以防有人可以确认是不是这样。

如果有人对在同步函数中间集成这个异步步骤的最佳方法有提示,那将是受欢迎的!

【讨论】:

    【解决方案2】:

    我正在为我的问题写一个最终答案,因为我找到了适合我特定用例的解决方案。

    尽管我的操作不应该是“异步”的,但我最终做的是将我的脚本拆分为“job.done();”继续我的脚本的其余部分,使“编码”大部分类似于同步脚本。

    出于分享的目的,我删除了大部分内容,并尝试只保留有趣的部分。我希望这对任何尝试做类似事情的人来说已经足够了。这也是我发现的访问加速度计数据的最短方法。

    基本上,我的想法是我有一个switch,这取决于我可能需要传感器或者我可能不需要它的结果(只保留两个案例来说明我的观点)。 当case"portrait" 时,我可以保持一切同步,并调用“job.done();”这将继续脚本的其余部分。

    但是,如果case"auto_landscape",我想使用传感器。因为我只需要一次阅读,当传感器发送它的第一个回调 (onSensorChanged()) 时,它会注销自己,然后使用相同的 job.done(); 方法来完成脚本。

    这里是:

    sensorManager = (SensorManager) this.getSystemService(Context.SENSOR_SERVICE);
    
    switch(currentMode) {
        case "portrait":
            setRotation(0);
            job.done("Portrait");
            break;
    
        case "auto_landscape":
            sensorListener = new SensorEventListener() {
                @Override public void onAccuracyChanged(Sensor arg0, int arg1) {}
                @Override public synchronized void onSensorChanged(SensorEvent event) {
                    if (event.values[0] > 0 ) {
                        // landscape right
                        setRotation(1);
                    } else {
                        // landscape left
                        setRotation(3);
                    }
                    sensorManager.unregisterListener(sensorListener);
                    job.done("Landscape (auto)");
                }
            };
            sensorManager.registerListener(sensorListener, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_FASTEST );
            break;
        default:
            job.done("Something is wrong!");
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多