0

Я разрабатываю приложение для 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(); 
     } 

    } 

ответ

1

Это не выглядит как проблема связана с порядком, в котором записаны события. После того, как вы получите временную метку «не в порядке», последующие времена продолжают увеличиваться с новой отметки времени, а не старой. Вероятно, что происходит, системное время сбрасывается вашей сотовой сетью https://developer.android.com/reference/android/os/SystemClock.html.

Решение зависит от ваших требований. В этом случае вы могли вспомнить последний раз, написанный и отбросив все показания датчиков ранее того времени. В качестве альтернативы вы можете настроить временную метку относительно времени начала записи с использованием метода uptimeMillis().

+0

да сон. проблема заключается в 'System.currentTimeMillis()', который может быть изменен сетевым провайдером. Теперь я использую 'SystemClock.elapsedRealTime()', который не зависит от часов пользователя. –

+0

не могли бы вы рассказать о времени? Дает ли вам абсолютное время (время unix) или относительное время (время работы от загрузки)? –

0

Попробуйте следующее (добавлено 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); 
    } 
} 
+0

, но в документах говорится, что функция выполнения назначает задачу в очереди для одного фонового потока или пула потоков в зависимости от версии платформы. При первом вводе AsyncTasks выполнялись последовательно на одном фоновом потоке. Начиная с DONUT, это было изменено на пул потоков, позволяющий нескольким задачам работать параллельно. Начиная HONEYCOMB, задачи возвращаются к выполнению в одном потоке, чтобы избежать общих ошибок приложений, вызванных параллельным выполнением. Все мои устройства работают над HONEYCOMB. –

+0

Нет, это не сработало. Около 1-2% моих данных не находятся в последовательном порядке. –

+1

на самом деле, добавив, что 'synchronzed' будет просто гарантировать, что запуск AsyncTasks будет выполняться последовательно, но не будет гарантировать, что они будут выполнены. Следующее содержит некоторые идеи о том, как их запускать в последовательности http: // stackoverflow.com/questions/7494515/can-i-chain-async-task-sequential-starting-one-after-the-previous-asynctask-c –