Запись данных датчика акселерометра в файл не в порядке

Я занимаюсь разработкой приложения для Android, которое будет записывать данные временной метки и датчика 3-осевого акселерометра (timestamp,ax,ay,az) в CSV-файл. Я получаю две проблемы, во-первых, что временная метка нескольких записей не записана в порядке возрастания в файле (см. Желтую выделенную метку времени на изображении). image1

Во-вторых, я получаю много записей для одной временной отметки (а не повторяющихся записей), в идеале мы должны получать только одну запись для уникальной временной отметки. image2,

Дизайн моего приложения: я создаю сервис, который будет работать в фоновом режиме и записывать все данные датчика в файл. Я использую 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);
    }
} 
Другие вопросы по тегам