防止onSensorChanged()

时间:2016-11-17 23:28:55

标签: android multithreading wear-os sensormanager

所以我一直在努力应对这一挑战,探索不同的可能性并缩小“排队”的位置。发生。我先解释一下我要做的事情。

我想做什么?
我正在使用可穿戴服务(在Sony Smartwatch 3上运行)编写一个Android应用程序(在Google Pixel上运行),以便尽快从智能手表中检索传感器数据,并将结果记录为详细信息。目前这种情况发生在150Hz左右,来自TYPE_ROTATION_VECTOR的数据。该数据使用PrintWriter通过信道(输出流)发送,并使用BufferReader在同一信道(输入流)上通过电话进行检索。我正在使用ChannelApi,因为DataApi确保了交付,但我的目标是尽可能快地将传感器数据传送到实时,其中数据丢失不太重要。我目前正在笔记本电脑上阅读ADB,以便在另一个应用程序中使用它。

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

  • 第一行:System.currentTimeMillis()在调用onSensorChanged()时观看
  • 第2行:来自event.timestamp
  • sensorEvent(除以1000000,从纳秒到毫秒)

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

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表示每20毫秒有一个读数。但是,onSensorChanged()不会以相同的间隔调用,或至少是一致性。要指出的是,即使在高速时,通道及其输入和输出写入器也能够跟上字节/消息的数量,即使在较长的时间段或时间内也是如此。

我尝试了什么?

我尝试从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();
}

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

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(基于thisthis Stackoverflow Q& A,因此它不会受到Activity或Service线程的影响然而,这也表现出与前面提到的相同的问题/挑战。

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:我可以使用传感器时间戳来计算/调整我在笔记本电脑上运行的程序。但是,我更喜欢只调整通信延迟(来自传感器 - >笔记本电脑应用程序,这可能是一个时不时改变的变量)而不是调整通信的不一致性(打印值的差异) ,需要为每次阅读计算。)

我希望这个漫长的(抱歉!)故事是有道理的,有人可以帮助我或指出我正确的方向!

1 个答案:

答案 0 :(得分:0)

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