0

Ich entwickle eine Android-App, die die Zeitstempel und 3-Achsen-Beschleunigungssensor-Daten (timestamp, ax, ay, az) in eine CSV-Datei schreiben wird. Ich bekomme zuerst zwei Probleme, weil der Zeitstempel einiger Einträge nicht in aufsteigender Reihenfolge in der Datei geschrieben ist (siehe den gelb markierten Zeitstempel im Bild). image1Schreiben von Beschleunigungssensor Daten in Datei ist außer Betrieb

Zweite ist, dass ich viele Einträge für einen einzigen Zeitstempel bin immer (nicht die doppelten Einträge), im Idealfall sollten wir nur einen einzigen Eintrag für einen einzigartigen Zeitstempel image2 bekommen.

Das Design meiner App ist: Ich erstelle einen Dienst, der im Hintergrund läuft und alle Sensordaten in eine Datei speichert. Ich verwende ZipOutputStream, der BufferedOutputStream und FileOutputStream zum Schreiben von Sensordaten in die Datei umschließt. Unten ist das Code-Snippet von AccelerometerLoggingService. Ich schließe die Datei in onDestroy() Methode des Dienstes. Können Sie mir vorschlagen, was die möglichen Fehler in meinem Code oder Design sein können? Ich denke, es kann ein Problem mit Threading geben, aber ich weiß nicht, wie man es debuggt. Jede Hilfe wird geschätzt.

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:

Ich dachte, das Problem, weil der Thread-Synchronisation war. Deshalb habe ich mich entschieden, den Beschleunigungssensor auf einem separaten Hintergrund-Thread laufen zu lassen und Sensordaten in die Datei im selben Thread zu schreiben, aber immer noch bekomme ich keine Einträge in meinen Dateien. Unten sind die neuen Codeänderungen, die ich gemacht habe.

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

    } 

Antwort

1

Es ist nicht wie das Problem sieht auf die auftragsbezogene, in der Ereignisse geschrieben werden. Nachdem Sie den Zeitstempel "out of order" erhalten haben, erhöhen sich die nachfolgenden Zeiten von dem neuen Zeitstempel und nicht vom alten. Wahrscheinlich wird die Systemzeit von Ihrem Mobilfunknetz zurückgesetzt https://developer.android.com/reference/android/os/SystemClock.html.

Die Lösung hängt von Ihren Anforderungen ab. In diesem Fall könnten Sie sich an das letzte Mal erinnern, zu dem Sie die Sensorwerte früher geschrieben und gelöscht haben. Alternativ können Sie den Zeitstempel relativ zur Zeit der Aufnahme mit der uptimeMillis() -Methode anpassen.

+0

ja Nickerchen. Das Problem liegt bei 'System.currentTimeMillis()', das vom Netzwerkanbieter geändert werden kann. Jetzt verwende ich 'SystemClock.elapsedRealTime()', das unabhängig von der Uhr des Benutzers ist. –

+0

Können Sie bitte die Zeit näher erläutern? Gibt es die absolute Zeit (Unix-Zeit) oder relative Zeit (Uptime vom Start)? –

0

Versuchen folgende (hinzugefügt 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); 
    } 
} 
+0

Dokumentation besagt jedoch, dass die Ausführungsfunktion die Aufgabe in einer Warteschlange für einen einzelnen Hintergrundthread oder Threadpool plant, der von der Plattformversion abhängt. Bei der ersten Einführung wurden AsyncTasks seriell in einem einzelnen Hintergrundthread ausgeführt. Beginnend mit DONUT wurde dies in einen Pool von Threads geändert, der es mehreren Tasks ermöglichte, parallel zu arbeiten. Beim Starten von HONEYCOMB werden Tasks wieder in einem einzelnen Thread ausgeführt, um häufige Anwendungsfehler zu vermeiden, die durch die parallele Ausführung verursacht werden. Alle meine Geräte laufen über HONEYCOMB. –

+0

Nein, es hat nicht funktioniert. Etwa 1-2% meiner Daten sind nicht sequentiell. –

+1

tatsächlich, fügt hinzu, dass 'synchronisierte' wird nur sicherstellen, dass AsyncTasks wird nacheinander ausgeführt werden, wird aber nicht garantieren Reihenfolge, dass sie ausgeführt werden .... folgende hat einige Ideen, wie Sie sie in Folge http ausführen: // stackoverflow.com/questions/7494515/can-i-chain-async-task-sequentially-starting-one-after-the-previous-asynctask-c –

Verwandte Themen