Запись данных датчика акселерометра в файл не в порядке
Я занимаюсь разработкой приложения для Android, которое будет записывать данные временной метки и датчика 3-осевого акселерометра (timestamp,ax,ay,az) в CSV-файл. Я получаю две проблемы, во-первых, что временная метка нескольких записей не записана в порядке возрастания в файле (см. Желтую выделенную метку времени на изображении).
Во-вторых, я получаю много записей для одной временной отметки (а не повторяющихся записей), в идеале мы должны получать только одну запись для уникальной временной отметки. ,
Дизайн моего приложения: я создаю сервис, который будет работать в фоновом режиме и записывать все данные датчика в файл. Я использую ZipOutputStream, который оборачивает BufferedOutputStream и FileOutputStream для записи данных датчика в файл. Ниже приведен фрагмент кода AccelerometerLoggingService
, Я закрываю файл в onDestroy()
метод обслуживания. Можете ли вы предложить мне, какие могут быть возможные недостатки в моем коде или дизайне. Я думаю, что может быть какая-то проблема с многопоточностью, но я не знаю, как ее отладить. Любая помощь приветствуется.
public class AccelerometerLoggingService extends Service {
class AccelerometerEventLoggerTask extends AsyncTask<Acceleration, Void, Void> {
@Override
protected Void doInBackground(Acceleration... accelerations) {
Acceleration acc = accelerations[0];
writeAcceleration(acc);
return null;
}
}
class AccelerometerSensorListener implements SensorEventListener {
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER)
return;
Acceleration acc = new Acceleration(System.currentTimeMillis(),
event.values[0],
event.values[1],
event.values[2]);
new AccelerometerEventLoggerTask().execute(acc);
}
}
}
writeAcceleration(Acceleration acc) {
zipOutputStream.write(acc.toString().getBytes());
}
//
ZipOutputStream zipOutputStream = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(logFile)));
Обновление 2:
Я думал, что проблема была из-за синхронизации потоков. Поэтому я решил запустить датчик акселерометра в отдельном фоновом потоке и записать данные датчика в файл в том же потоке, но все же я получаю записи о порядке в моих файлах. Ниже приведены новые изменения кода, которые я сделал.
public void startAccelerometer() {
// creating new thread for onSensorChanged method to run
handlerThread = new HandlerThread("AccelerometerSensorThread");
handlerThread.start();
handler = new Handler(handlerThread.getLooper());
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mAccelerometerSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(this, mAccelerometerSensor, SensorManager
.SENSOR_DELAY_GAME, handler);
}
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER)
return;
Acceleration acc = new Acceleration(System.currentTimeMillis(),
event.values[0],
event.values[1],
event.values[2]);
accelerometerLogger.writeAcceleration(acc); // writing sensor data to file
Log.d(TAG, "onSensorChanged Thread name " + Thread.currentThread().getName()); // AccelerometerSensorThread
}
public void stopAccelerometer() {
// first unregister the sensor listener then stop the thread
mSensorManager.unregisterListener(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
handlerThread.quitSafely();
} else {
handlerThread.quit();
}
}
2 ответа
Не похоже, что проблема связана с порядком записи событий. После того, как вы получите временную метку "не в порядке", последующие значения продолжат увеличиваться с новой, а не старой. Вероятно, происходит то, что системная сеть сбрасывает системное время https://developer.android.com/reference/android/os/SystemClock.html.
Решение зависит от ваших требований. В этом случае вы можете вспомнить последний раз, когда он записал, и отменить любые показания датчика ранее, в это время. В качестве альтернативы вы можете настроить метку времени относительно времени начала записи, используя метод uptimeMillis().
Попробуйте следующее (добавлено synchronized
блок)
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER)
return;
synchronized(this) {
Acceleration acc = new Acceleration(System.currentTimeMillis(),
event.values[0],
event.values[1],
event.values[2]);
new AccelerometerEventLoggerTask().execute(acc);
}
}