防止 onSensorChanged() 排队不一致

Prevent inconsistent queuing of onSensorChanged()

所以我一直在努力应对这个挑战,探索不同的可能性并缩小 'queuing' 发生的位置。让我先解释一下我想做什么。

我想做什么?
我正在编写一个 Android 应用程序(运行 在 Google Pixel 上)和可穿戴服务(运行 在 Sony Smartwatch 3 上)以最快的速度从智能手表检索传感器数据可能,将结果记录为 Verbose。这目前发生在 150Hz 左右,来自 TYPE_ROTATION_VECTOR 的数据。此数据使用 PrintWriter and retreived by the phone on the same channel (inputstream) using a BufferReader 通过通道(输出流)发送。我正在使用 ChannelApi,因为 DataApi 确保交付,但我的目标是尽可能快地实时交付传感器数据,其中数据丢失不太重要。我目前正在我的笔记本电脑上阅读 ADB,以便在另一个应用程序中使用它。

问题/挑战是什么?
在我的程序的几个阶段获得系统时间后,我发现数据排队不是 ADB 连接的错误,也不是输入或输出流的错误,也不是 printwriter 的错误。似乎函数 onSensorChanged() 不会在 sensorEvent 发生时立即调用。为了说明,下面是每个 onSensorChanged() 事件作为数据发送的时间,其中 sensorListener 设置为 SENSOR_DELAY_GAME(但也占 SENSOR_DELAY_FASTEST.

这给出了一些传感器读数的概述:

1479407287638;    687629;
1479407287638;    687649;
1479407287681;    687669;
1479407287681;    687689;
1479407287718;    687709;
1479407287718;    687729;
1479407287768;    687749;
1479407287768;    687769;
1479407287810;    687789;
1479407287811;    687809;

如果您查看时间之间的差异,您会得到:

-      -
 0;    20
49;    20
 0;    20
37;    20
 0;    20
50;    20
 0;    20
42;    20
 1;    20

如您所见,sensorTimestamp表示每20ms有一个读数。但是, onSensorChanged() 不会以相同的时间间隔调用,或者至少不会保持一致性。需要指出的是,即使在高速情况下,Channel 及其输入和输出编写器也能够跟上 bytes/messages 的数量,即使在更长的周期或时间上也是如此。

我尝试了什么?

我试图从 onSensorChanged

中删除所有任务
 public void onSensorChanged(SensorEvent event) {
    final int accuracy = event.accuracy;
    final long timestamp = event.timestamp;
    final float[] values = event.values;
    final String sensorName = event.sensor.getStringType();

    if (data_transfer) {                        // if interaction is initiated
        printWriter.println(message);
    }
}

我试图从 onSensorChanged 中删除所有任务并在启动线程的其他地方执行它们

if (data_transfer) {                        // if interaction is initiated
    new Thread(new convertAndSend(sensorName,timestamp,accuracy,values)).run();
}

起初我将可穿戴应用编写为 activity,但我也将其转换为服务(运行 在后台)

public class SensorService extends Service implements SensorEventListener {
...
    public void onSensorChanged(SensorEvent event) {
        client.sendSensorData(event.sensor.getType(), event.accuracy, event.timestamp/1000000, event.values); //client takes care of outputstream
    }
}

最后,我考虑在一个单独的线程中实现 SensorEventListener(基于 this and this Whosebug Q&A,因此它不会受到 Activity 或服务线程的影响。但是,这也显示了与之前提到的相同的问题/挑战。

public class SensorListenerThread implements Runnable {

    private static final String TAG = "SensorService";
    private final static int SENS_ROTATION_VECTOR = Sensor.TYPE_ROTATION_VECTOR;

    SensorManager mSensorManager;

    @Override
    public void run() {
        Log.d( "RunTag", Thread.currentThread().getName() ); // To display thread

        mSensorManager = ((SensorManager)getSystemService(SENSOR_SERVICE));

        Looper.prepare();
        Handler handler = new Handler(){
            // process incoming messages here??
        };
        Sensor rotationVectorSensor = mSensorManager.getDefaultSensor(SENS_ROTATION_VECTOR);
        MySensorListener msl = new MySensorListener();
        mSensorManager.registerListener(msl, rotationVectorSensor, SensorManager.SENSOR_DELAY_FASTEST, handler);

        Looper.loop();
    }

    private class MySensorListener implements SensorEventListener {
        public void onAccuracyChanged (Sensor sensor, int accuracy) {}
        public void onSensorChanged(SensorEvent sensorEvent) {
            Log.d( "ListenerTag", Thread.currentThread().getName() ); // To display thread
        }
    }

}

求助!
我的理解是 onSensorChanged 事件被调用,但与传感器的时间戳似乎指示的时间不同。速度和使用频道效果很好,但我似乎无法解决此问题。我有一个 B 计划:我可以使用传感器时间戳来 calculate/adjust 我在笔记本电脑上 运行 的程序。但是,我更喜欢只调整通信延迟(来自传感器 --> 笔记本电脑应用程序,这可能是一个不时更改的变量),而不是调整通信的不一致(打印值的差异,每次读数都需要计算)。

我希望这个冗长(抱歉!)的故事有意义,并且有人可以帮助我或为我指明正确的方向!

看起来,可能无法依赖对 onSensorChanged() 的一致调用。因此,我使用时间戳而不是 onSensorChanged 的​​时间。我会建议其他人也这样做!