2

I want to display the time which the first step was detected. But the app always shows Jan 01 1970. Would some one check what is wrong and how to change it? Here is my code:

public void run() {
    SensorManager mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    Sensor mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);

    mSensorManager.registerListener(new SensorEventListener() {
        @Override
        public void onSensorChanged(SensorEvent sensorEvent) {
            long timeStamp = sensorEvent.timestamp / 1000000;
            textView_moveTime.setText(DateUtils.getRelativeTimeSpanString(timeStamp));
        }

        @Override
        public void onAccuracyChanged(Sensor sensor, int i) {

        }
    }, mSensor, mSensorManager.SENSOR_DELAY_FASTEST);
}
Allan Pereira
  • 2,572
  • 4
  • 21
  • 28
Yongyi Wu
  • 21
  • 1
  • 1
  • I think Jan 01 1970 equates to 0 (i.e. start of date/time). So perhaps look to see if 0 is being returned/set. – MikeT Aug 07 '16 at 22:15
  • Since `timestamp` is nanosecond-level precision, it is unlikely to be in the Unix epoch timebase, so dividing by 1000000 is unlikely to work. It might be using the same system [as `nanoTime()`](https://developer.android.com/reference/java/lang/System.html#nanoTime()), in which case you only use it for computing relative times from some starting point. – CommonsWare Aug 07 '16 at 22:15
  • Thank you very much! I think I find the reason. – Yongyi Wu Aug 31 '16 at 16:28

2 Answers2

1

SensorEvent reports time in nanoseconds since system boot (including sleep time). To convert it to absolute time in nanos, use following formula:

(DateTime.now().getMillis() - SystemClock.elapsedRealtime()) * 1000000
                + sensorEvent.timestamp
vvm
  • 136
  • 2
  • sorry, but what is "DateTime"... AS doesn't recognize this as a valid class of anything. – Michael Jan 08 '20 at 22:29
  • I guess, we can replace `DateTime.now().getMillis()` with `System.currentTimeMillis().` – Sagar Patel Jan 19 '23 at 11:57
  • The base of the `SystemClock.elapsedRealTime()` and `SensorEvent.timestamp` can be different (relative since boot) than the base of the `DateTime.now().getMillis()` or `System.currentTimeMillis()` (wall clock time). Should it still work? – Sagar Patel Jan 19 '23 at 13:09
  • I have checked it, and it is working. However, I could not understand how and why because I guess the base of the `System.currentTimeMillis()` might be different than the base of the `SystemClock.elapsedRealtime()`. – Sagar Patel Jan 24 '23 at 14:17
0

SensorEvent.timestamp is when the event happened, but it is an elapsed time since boot. It is not the exact timestamp of when the event happened. We want to get the actual time when the event happened from the elapsed time since the event happened.

Reference: https://developer.android.com/reference/android/hardware/SensorEvent#timestamp

  1. We need all the entities in a similar unit. We are taking Millis here.
  2. We have three entities to use. a) System.currentTimeMillis() b) SystemClock.elapsedRealtime() and c) SensorEvent.timestamp

enter image description here

  1. If we use SystemClock.elapsedRealtimeNanos(), then we need to convert it into Millis as below:
val systemCurrentTimeMillis = System.currentTimeMillis()
val systemClockElapsedRealtimeMillis = TimeUnit.NANOSECONDS.toMillis(SystemClock.elapsedRealtimeNanos())
val sensorEventTimeStampMillis = TimeUnit.NANOSECONDS.toMillis(sensorEvent.timestamp)
  1. We need to find the difference between the systemCurrentTimeMillis, and systemClockElapsedRealtimeMillis as below:

enter image description here

val currentMinusElapsedRealtimeMillis = systemCurrentTimeMillis - systemClockElapsedRealtimeMillis
  1. Once we find the difference, we need to add sensorEventTimeStampMillis to it as below:

enter image description here OR enter image description here

val actualEventTimeMillis = currentMinusElapsedRealtimeMillis + sensorEventTimeStampMillis
  1. Then, we need to convert the result into UTC as below (I am using Joda Time):
val actualEventTimeUtc = DateTime(actualEventTimeMillis, DateTimeZone.UTC)

The actualEventTimeUtc is the absolute time when the event happened.

Another way to understand it is:

Suppose the sensor reports an event in onSensorChanged. We find that the current time is: 13 PM. In other words, the reporting time is 13 PM and it is not the time when the actual event happened.

The SystemClock.elapsedRealtime() says that it has been running since last 30 hours. In other words, it started 30 hours before from the current time.

So, we subtract the 30 hours from the current time to get the time when the sensor started. So, we get 7 AM of the previous day.

The SensorEvent.timestamp says that the event happened after 28 hours of the SystemClock.elapsedRealtime().

Hence, we add 28 hours to the 7 AM of the previous day. So, we get 11 AM of the current day and it is the actual time when event happened.

Sagar Patel
  • 506
  • 1
  • 8
  • 23