0

我開發的Android應用,這將寫出的時間戳和3軸加速度計傳感器數據(時間戳,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

嘗試以下(加​​塊)

@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-sequentially-starting-one-after-the-previous-asynctask-c –