2016-11-17 78 views
0

排队不一致所以我一直在努力解决这个挑战一段时间,探索不同的可能性和缩小'排队'发生的地方。让我先解释一下我正在尝试做什么。防止onSensorChanged()

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

问题/挑战是什么?
在我的程序的几个阶段获得系统时间后,我发现数据排队不是ADB连接的错误,也不是输入或输出流,也不是printwriter。看起来功能onSensorChanged()不会立即被调用,因为发生了sensorEvent。为了说明这一点,下面是时间发送数据,对于每一个onSensorChanged()事件,与sensorListener设置为SENSOR_DELAY_GAME(但也占SENSOR_DELAY_FASTEST

  • 第一行:System.currentTimeMillis()上时onSensorChanged()
  • 第二手表行:在event.timestamp(由百万分从纳米到毫秒去)从sensorEvent

这给出了几个传感器读数的概述:

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()不会以相同的时间间隔或至少一致性进行调用。要指出的是,即使在高速情况下,通道及其输入和输出写入器也能够跟上字节/消息的数量,即使在更长的时间或更长的时间内也是如此。

我试过了什么?

我试图从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,所以它不会受到活动或服务线程的影响。但是,这也表明了与前面提到的相同的问题/挑战。

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

我希望这漫长的(对不起!)的故事是有道理的,有人可以帮我或点我在正确的方向!

+0

你可能要检查使用[工作线程(https://developer.android.com/guide/components/processes-and-threads.html)来处理更复杂的交互。正如在给定的文档中提到的,您可能会考虑在您的工作线程中使用[Handler](https://developer.android.com/reference/android/os/Handler.html)来处理从UI线程传递的消息。也许最好的解决方案是扩展[AsyncTask类](https://developer.android.com/reference/android/os/AsyncTask.html),它简化了需要与UI交互的工作线程任务的执行。 – Teyam

+0

hi @Teyam,我已经实现了一个工作线程来接收onSensorchanged()消息。它不再干扰UI线程。然而,在这种情况下,消息也是以一致的时间间隔接收的。我希望能够以传感器消息(时间戳)和接收消息(onSensorChanged)之间的时间一致的方式构建代码。我现在必须查看传感器时间戳并计算出现的相应时间。 – Dave

回答

0

,因为它似乎,它可能无法依靠onSensorChanged的一致()调用。因此,我使用时间戳而不是onSensorChanged的时间。我会建议其他人也这样做!