我的应用程序使用android 4.4.X中引入的step detector sensor API's进行后台步骤计数。
我的应用程序必须知道每个步骤事件产生的确切时间(至少准确度为一秒)。
因为我执行了sensor batching,所以调用时间onSensorChanged(SensorEvent event)
与步骤事件发生的时间不同 - 我必须使用event.timestamp
字段来获取事件时间。< / p>
有关此字段的文档是:
事件发生的纳秒时间
问题:
在某些设备(例如Moto X 2013)中,这个时间戳似乎是自启动以来的纳秒时间,而在某些设备(例如Nexus 5)中,它实际上以与System.currentTimeMills() / 1000
相同的纳秒为单位返回通用系统时间。
据我所知,已经有 old open issue,但由于引入了传感器批处理 - 使用此字段来了解事件时间变得非常重要,并且不可能依赖已经System.currentTimeMills()
我的问题:
如何在所有设备上始终以系统毫秒为单位获取事件时间?
答案 0 :(得分:6)
您可以检查event.timestamp
是否小于“{2}”,而不是“2天”比较。 1262304000000000000
- 这样,如果过去设置了用户的时钟,或者他们的手机已经运行了40年,那么您只会遇到问题...
除了 this issue上的评论表示有时它甚至是毫秒而不是纳秒。其他评论表明应用了偏移量,在这种情况下,它不会是系统时间或基于正常运行时间。
如果你真的必须准确,我唯一能看到的方法是最初捕获一个事件(或两个,用于比较),max_report_latency_ns
设置为0
(即非批处理)和将时间戳与系统时间和/或elapsedRealtime
进行比较。然后使用该比较来计算偏移量(并可能决定是否需要补偿毫秒与纳秒之间的关系)并将该偏移量用于批处理事件。
E.g。抓住几个事件,最好相隔几秒钟,每次记录System.currentTimeMillis()
,然后做这样的事情:
long timestampDelta = event2.timestamp - event1.timestamp;
long sysTimeDelta = sysTimeMillis2 - sysTimeMillis1;
long divisor; // to get from timestamp to milliseconds
long offset; // to get from event milliseconds to system milliseconds
if (timestampDelta/sysTimeDelta > 1000) { // in reality ~1 vs ~1,000,000
// timestamps are in nanoseconds
divisor = 1000000;
} else {
// timestamps are in milliseconds
divisor = 1;
}
offset = sysTimeMillis1 - (event1.timestamp / divisor);
然后是你的批量活动
long eventTimeMillis = (event.timestamp / divisor) + offset;
最后一点需要注意 - 即使你做了所有这些,如果在捕获过程中系统时间发生变化,也可能会影响你的时间戳。祝你好运!
答案 1 :(得分:3)
根据您提问中的link:
事实上,这是“按预期工作”。时间戳不是 定义为Unix时间;他们只是“时间”而已 对给定的传感器有效。这意味着时间戳只能是 比较它们是否来自同一传感器。
因此,timestamp
- 字段可能与当前系统时间完全无关。
然而;如果在启动时你要拍摄两个传感器样本,没有批处理,你可以计算System.currentTimeMillis()
和时间戳之间的差异,以及不同时间之间差异的商数应该能够在不同时间之间进行转换:
//receive event1:
long t1Sys = System.currentTimeMillis();
long t1Evt = event.timestamp;
//receive event2:
long t2Sys = System.currentTimeMillis();
long t2Evt = event.timestamp;
//Unregister sensor
long startoffset = t1Sys - t1Evt; //not exact, but should definitely be less than a second, possibly use an averaged value.
long rateoffset = (t2Sys - t1Sys) / (t2Evt - t1Evt);
现在可以转换来自该传感器的任何时间戳
long sensorTimeMillis = event.timestamp * rateoffset + startoffset;
答案 2 :(得分:2)
我找到了解决问题的解决方法。解决方案假定时间戳只能是两个中的一个:系统时间戳或启动时间:
protected long getEventTimestampInMills(SensorEvent event) {
long timestamp = event.timestamp / 1000 / 1000;
/**
* work around the problem that in some devices event.timestamp is
* actually returns nano seconds since last boot.
*/
if (System.currentTimeMillis() - timestamp > Consts.ONE_DAY * 2) {
/**
* if we getting from the original event timestamp a value that does
* not make sense(it is very very not unlikely that will be batched
* events of two days..) then assume that the event time is actually
* nano seconds since boot
*/
timestamp = System.currentTimeMillis()
+ (event.timestamp - System.nanoTime()) / 1000000L;
}
return timestamp;
}