如何在请求时仅读取一次 Android 传感器数据

How to read Android Sensor data only once, when asked for

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

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

这不是我想要的,而且我认为我想做的可能是不可能的。

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

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

感觉像anysensor.getCurrentState()一样拥有足够的权限后,应该是一个简单的一行操作。 但是据我所知,我只找到依赖于 sensorManager 事件侦听器的文档,并且必须设置整个 class 和 5 个不同的事件回调:

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

我想我可以做到这一点,并尝试让它尽可能轻,让 eventListeners 在第一次阅读时自动停止。但它感觉很潮,而且有很多代码可以满足我的需要。而且我正在尝试做一个非常简单的任务,阅读,了解它,然后完成它,这需要一些异步的东西。 所以我想我必须“暂停”应用程序,直到获得第一个结果。

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

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

Android get sensor data without EventListeners

我还没有结束这个问题,以防万一有人可以确认是这种情况还是其他情况。

如果有人有关于在同步函数中间集成此异步步骤的最佳方法的提示,我们将不胜感激!

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

尽管我的操作不应该是“异步的”,但我最终做的是拆分我的脚本,以便“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!");
}