防止 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.
- 第 1 行:当
onSensorChanged()
被调用时 System.currentTimeMillis()
在手表上
- 第 2 行:
sensorEvent
的 event.timestamp
(除以 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
表示每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 的时间。我会建议其他人也这样做!
所以我一直在努力应对这个挑战,探索不同的可能性并缩小 '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.
- 第 1 行:当
onSensorChanged()
被调用时System.currentTimeMillis()
在手表上 - 第 2 行:
sensorEvent
的
event.timestamp
(除以 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
表示每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 的时间。我会建议其他人也这样做!