我目前正在开发一个安卓应用程序.. 我需要记录加速度传感器事件坐标以及事件时间。我已经获取了传感器事件的时间戳,像是"3497855005850",但我无法将事件时间戳转换为用户可读的日期时间格式。提前致谢。
如何将SensorEvent的时间戳转换为Unix时间戳?
我目前正在开发一个安卓应用程序.. 我需要记录加速度传感器事件坐标以及事件时间。我已经获取了传感器事件的时间戳,像是"3497855005850",但我无法将事件时间戳转换为用户可读的日期时间格式。提前致谢。
如何将SensorEvent的时间戳转换为Unix时间戳?
传感器时间戳实际上是设备已运行时间的纳秒数,而不是系统时间的纳秒数。请参见SensorEvent.timestamp to absolute (utc) timestamp?.
理论上,你可以使用以下方法将传感器时间戳转换为毫秒级时间:
long timeInMillis = (new Date()).getTime()
+ (sensorEvent.timestamp - System.nanoTime()) / 1000000L;
你甚至可以使用两个System.nanoTime()
调用来框定(new Date()).getTime()
调用,并对它们进行平均以更接近实际偏移量。
然后,您可以将传感器时间格式化为日期和时间。
onSensorChanged(SensorEvent)
函数中设置参考时间变量。private long sensorTimeReference = 0l;
private long myTimeReference = 0l;
public void onSensorChanged(SensorEvent event) {
// set reference times
if(sensorTimeReference == 0l && myTimeReference == 0l) {
sensorTimeReference = event.timestamp;
myTimeReference = System.currentTimeMillis();
}
// set event timestamp to current time in milliseconds
event.timestamp = myTimeReference +
Math.round((event.timestamp - sensorTimeReference) / 1000000.0);
// some code...
}
https://source.android.com/devices/sensors/hal-interface.html#sensors_event_t
"timestamp必须与elapsedRealtimeNano时钟同步"
val timeInMills = System.currentTimeMillis() + (event.timestamp - SystemClock.elapsedRealtimeNanos()) / 1000000
(event.timestamp - SystemClock.elapsedRealtimeNanos())
添加到 System.currentTimeMillis()
中?这不会使实际事件时间超过当前时间吗? - Sagar PatelSystemClock.elapsedRealtimeNanos()
和SensorEvent.timestamp
的基准(自启动以来的相对时间)可能与System.currentTimeMillis()
(挂钟时间)的基准不同。它仍然能正常工作吗? - Sagar PatelSensorEvent#timestamp
文档表明:
挑战[事件时间为] 事件发生时的纳秒级时间。 对于给定的传感器,每个新的传感器事件应该使用与SystemClock.elapsedRealtimeNanos()相同的时间基准单调递增。
SystemClock.currentTimeNanos()
(例如Nexus 4)。/**
* Calculates the static offset (ms) which needs to
* be added to the `event.time` (ns) to get the Unix
* timestamp of the event.
*
* @param eventTimeNanos the {@code SensorEvent.time} to be used to determine the time offset
* @return the offset in milliseconds
*/
private long eventTimeOffset(final long eventTimeNanos) {
// Capture timestamps of event reporting time
final long elapsedRealTimeMillis = SystemClock.elapsedRealtime();
final long upTimeMillis = SystemClock.uptimeMillis();
final long currentTimeMillis = System.currentTimeMillis();
// Check which timestamp the event.time is closest to the event.time
final long eventTimeMillis = eventTimeNanos / 1_000_000L;
final long elapsedTimeDiff = elapsedRealTimeMillis - eventTimeMillis;
final long upTimeDiff = upTimeMillis - eventTimeMillis;
final long currentTimeDiff = currentTimeMillis - eventTimeMillis;
// Default case (elapsedRealTime, following the documentation)
if (Math.abs(elapsedTimeDiff) <= Math.min(Math.abs(upTimeDiff), Math.abs(currentTimeDiff))) {
final long bootTimeMillis = currentTimeMillis - elapsedRealTimeMillis;
return bootTimeMillis;
}
// Other seen case (currentTime, e.g. Nexus 4)
if (Math.abs(currentTimeDiff) <= Math.abs(upTimeDiff)) {
return 0;
}
// Possible case, but unknown if actually used by manufacturers (upTime)
throw new IllegalStateException("The event.time seems to be upTime. In this case we cannot use a static offset to calculate the Unix timestamp of the event");
}
注册时间延迟
关于“可能的情况”(参见代码):
目前不清楚是否有任何制造商实际上使用upTime
作为event.time
。因此,我们抛出一个异常来看看是否会发生这种情况。
如果确实发生了这种情况,并且我们计算了currentTime
和upTime
之间的静态偏移量,这将导致设备再次进入(深度)睡眠时出现时间偏移。我们需要为每个事件动态地计算偏移量,这相当耗费资源。
如果在设备上发生这种情况,则可以使用以下方法进行测试:https://developer.android.com/training/monitoring-device-state/doze-standby#testing_doze_and_app_standby
我看到三种获取毫秒的方法(Kotlin)
val millis = Date().getTime() + (event.timestamp - System.nanoTime()) / 1000000L
val millis = System.currentTimeMillis() + (event.timestamp - System.nanoTime()) / 1000000L
val millis = System.currentTimeMillis() + (event.timestamp - SystemClock.elapsedRealtimeNanos()) / 1000000L
这三种方法都能得到相同的结果,但是当我想要查看从计算值到当前时间的差异时
val diff = System.currentTimeMillis() - millis
我看到'value'为-359704905的'diff'?
Log.d("diff", "" + event.timestamp + " - " + System.nanoTime())
差异: 541695268300000 - 181990403666592
差异: 541695277240000 - 181990405818592
差异: 541695286859000 - 181990411901592
差异: 541695296139000 - 181990412584592
差异: 541695305735000 - 181990415222592
因此,所有建议的解决方案都不正确
对我来说,这种简单的方法适合我的需求
override fun onSensorChanged(sensorEvent: SensorEvent?) {
val millis = System.currentTimeMillis()
}
SensorEvent.timestamp
是事件发生时的经过时间,但它是自启动以来经过的时间。它不是事件发生的时间。我们需要从事件发生后经过的时间中获取事件实际发生的时间。
参考: https://developer.android.com/reference/android/hardware/SensorEvent#timestamp
Millis
。System.currentTimeMillis()
b) SystemClock.elapsedRealtime()
和 c) SensorEvent.timestamp
SystemClock.elapsedRealtimeNanos()
,那么我们需要将其转换为以下Millis
:val systemCurrentTimeMillis = System.currentTimeMillis()
val systemClockElapsedRealtimeMillis = TimeUnit.NANOSECONDS.toMillis(SystemClock.elapsedRealtimeNanos())
val sensorEventTimeStampMillis = TimeUnit.NANOSECONDS.toMillis(sensorEvent.timestamp)
systemCurrentTimeMillis
和 systemClockElapsedRealtimeMillis
。val currentMinusElapsedRealtimeMillis = systemCurrentTimeMillis - systemClockElapsedRealtimeMillis
sensorEventTimeStampMillis
添加到它上面:
val actualEventTimeMillis = currentMinusElapsedRealtimeMillis + sensorEventTimeStampMillis
Joda Time
):val actualEventTimeUtc = DateTime(actualEventTimeMillis, DateTimeZone.UTC)
actualEventTimeUtc
是事件发生的绝对时间。onSensorChanged
中报告了一个事件。我们发现当前时间是13点。换句话说,报告时间是下午1点,而不是实际事件发生的时间。
SystemClock.elapsedRealtime()
显示它已经运行了30个小时。换句话说,它在当前时间30小时前启动。SystemClock.elapsedRealtime()
后的28小时。