0

타임 스탬프 및 3 축 가속도계 센서 데이터 (timestamp, ax, ay, az)를 csv 파일에 쓰는 Android 앱을 개발 중입니다. 나는 두 가지 문제점을 제일 먼저 겪고있다. 몇 가지 엔트리의 타임 스탬프가 파일의 오름차순으로 기록되지 않는다. (이미지에서 노란색으로 강조 표시된 타임 스탬프 참조). image1파일에 가속도계 센서 데이터 쓰기 중 오류가 발생했습니다.

두 번째는 내가 이상적으로 우리 고유의 타임 스탬프 image2을위한 단 하나의 항목을 받아야 하나의 타임 스탬프 (안 중복 된 항목)에 대한 여러 항목을 얻고 있다는 점이다.

내 디자인은 다음과 같습니다. 나는 백그라운드에서 실행될 서비스를 만들고 모든 센서 데이터를 파일에 기록합니다. BufferedOutputStream 및 FileOutputStream을 감싸는 ZipOutputStream을 사용하여 센서 데이터를 파일에 씁니다. 다음은 코드 스 니펫 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

시간을 자세히 설명해 주시겠습니까? 절대 시간 (유닉스 시간) 또는 상대 시간 (부팅 시간)을 제공합니까? –

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

하지만 문서화에 따르면 execute 함수는 플랫폼 버전에 따라 단일 백그라운드 스레드 또는 스레드 풀에 대한 대기열에서 작업을 예약합니다. 처음 소개되었을 때 AsyncTask는 단일 백그라운드 스레드에서 순차적으로 실행되었습니다. DONUT으로 시작하여 여러 스레드가 병렬로 작동 할 수 있도록 스레드 풀로 변경되었습니다. HONEYCOMB를 시작하면, 병렬 실행으로 인한 공통 응용 프로그램 오류를 피하기 위해 작업이 단일 스레드에서 다시 실행됩니다. 내 모든 장치가 HONEYCOMB보다 위에 실행되고 있습니다. –

+0

아니, 작동하지 않았다. 내 데이터의 약 1-2 %가 순차적 순서가 아닙니다. –

+1

실제로'synchronized '를 추가하면 AsyncTasks가 순차적으로 실행되지만 실행될 순서는 보장되지 않습니다. 다음은 순차적으로 실행하는 방법에 대한 아이디어가 있습니다. stackoverflow.com/questions/7494515/can-i-chain-async-task-sequentially-starting-one-after-the-previous-asynctask-c –

관련 문제