简体   繁体   中英

Writing accelerometer sensor data to file is out of order

I am developing an Android app which will write the timestamp and 3-axis accelerometer sensor data (timestamp,ax,ay,az) to a csv file . I am getting two problems first is that timestamp of few entries are not written in ascending order in file (see the yellow highlighted timestamp in image). 图片1

Second is that I am getting many entries for a single timestamp(not the duplicate entries), ideally we should get only a single entry for a unique timestamp image2 .

The design of my app is: I am creating a service which will be running in background and log all sensor data to a file. I am using ZipOutputStream which wraps BufferedOutputStream and FileOutputStream to write sensor data to the file. Below is the code snippet of AccelerometerLoggingService . I am closing the file in onDestroy() method of service. Can you suggest me what can be the possible flaws in my code or design. I think there may be some issue with threading but I don't know how to debug it. Any help is appreciated.

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)));

Update 2:

I thought the problem was because of thread synchronisation. Therefore I decided to run the accelerometer sensor on a separate background thread and writing sensor data to the file in the same thread but still I am getting out of order entries in my files. Below is the new code changes that I did.

     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();
        }

    }

It doesn't look like the issue is related to the order in which events are written. After you get the "out of order" timestamp the subsequent times continue to increase from the new timestamp not the old one. Probably what is happening is the system time is being reset by your cellular network https://developer.android.com/reference/android/os/SystemClock.html .

The solution depends on your requirements. In this case you could remember the last time written and discard any sensor readings earlier that time. Alternatively you could adjust the timestamp to be relative to the time you started recording by using the uptimeMillis() method.

Try following (added synchronized block)

@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);
    }
} 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM