【问题标题】:Different values for nano time in different sensor data. How to figure them out?不同传感器数据中纳秒时间的不同值。如何弄清楚它们?
【发布时间】:2018-06-09 08:36:25
【问题描述】:

自从最新的 Android 更新 (v. 8) 以来,我在尝试读取传感器时发现了一个非常奇怪的行为。更具体地说,我说的是 WiFi 和蜂窝塔。这里有两个例子:

当我读取 WiFi 接入点信息数据并尝试使用此代码将 accessPoint.timestamp 转换为绝对时间戳时:

long timeInMillis = System.currentTimeMillis() + ((accessPoint.timestamp * 1000L -
                SystemClock.elapsedRealtimeNanos()) / 1000000L);

但是,当我使用 nearbyCellTowers = mTelephonyManager.getAllCellInfo(); 阅读 Cell Towers 时,相同的代码无法正常工作,我必须使用其他代码:

long timeInMillis = System.currentTimeMillis() + ((gsmRecord.getTimeStamp() -
                    System.nanoTime()) / 1000000L);

如果您没有注意到区别,那是在使用 SystemClock.elapsedRealtimeNanos()System.nanoTime()

根据 Android 文档 getTimeStamp() 是:

getTimeStamp(): 自启动以来此单元格信息的近似时间(以纳秒为单位)

WiFi 类似:

时间戳: 上次看到此结果时的时间戳(以微秒为单位)。

虽然描述看起来相同(自启动以来的时间),但值却完全不同。可以看到,WiFi时间戳相当于SystemClock.elapsedRealtimeNanos()的值,而CellInfo时间戳相当于System.nanoTime()

除非我调试并查看结果,否则我永远不能说哪一个可以与这两个函数中的哪一个一起工作。我在这里错过了什么吗?有人可以为我澄清一下吗?这两个函数的主要区别是什么?为什么描述相同的两个时间戳的值不同?

【问题讨论】:

  • 你好!您是否能够在所有平台上以任何方式解决此问题?我的意思是,根据我的理解,简单地使用 System.nanoTime 会破坏旧的 Android 版本。而如果我们想在不同的 Android 版本上使用不同的方法,我们需要具体了解哪些 Android 版本的行为方式。还是特定于供应商?
  • @FreeNickname 如果可能,请提供您的测试结果。

标签: java android timestamp elapsedtime nanotime


【解决方案1】:

ScanResult#timestampCellInfo#getTimeStamp() 不一样。从文档中看得很清楚。

ScanResult#timestamp

最后一次看到此结果时的时间戳(以微秒为单位)。

我认为“自启动”一词会让您感到困惑。这意味着计时器将在系统重新启动时重置(绝不意味着计时器在系统启动时启动)。

CellInfo#getTimeStamp()

自启动以来此单元格信息的近似时间(以纳秒为单位)

与上一个一样,计时器将在重启时重置。


WiFi 时间戳与 SystemClock.elapsedRealtimeNanos(),而 CellInfo 时间戳为 相当于 System.nanoTime()。

我认为您的意思是“可比较”的“兼容”。这里不存在兼容性问题。 SystemClock.elapsedRealtimeNanos()System.nanoTime() 都将时间表示为纳秒。

System.nanoTime()

返回正在运行的 Java 虚拟机的高分辨率时间源的当前值,以纳秒为单位。它在深度睡眠中停止

SystemClock.elapsedRealtimeNanos()

返回自启动后的纳秒。即使在睡眠中也会继续抽搐。




最后到FreeNickname的问题:

据我了解,简单地使用 System.nanoTime 会破坏旧 安卓版本。如果我们想在不同的地方使用不同的方法 Android版本,我们需要具体了解哪些版本 Android 以哪种方式运行。还是特定于供应商?

您可以在所有版本的 Android 中使用SystemClock#elapsedRealtime()。它在 API 级别 1 中引入。请注意,与 elapsedRealtimeNanos() 不同,它返回毫秒。

【讨论】:

  • 谢谢,阿内斯!我不确定我是否理解。 It means the timer will reset when system reboots (and it never means the timer starts when system boots) 在这种情况下,应该有一种方法来获取连接时间(将此计数器转换为时间戳)。此外,设备可能永远不会从ScanResult 连接到 wifi,因为它指的是周围所有接入点的列表,而不是设备连接到的接入点。请您提供此声明的来源吗? `计时器在设备开始接收小区信号时启动`对于这个语句也是。
  • You can use SystemClock#elapsedRealtime() in all versions of Android. It is introduced in API level 1. Note that unlike elapsedRealtimeNanos(), it returns milliseconds. - 可以理解。我的意思是,看起来我们应该使用不同的参考点将有问题的“时间戳”转换为 unix 时间戳。在某些情况下,我们需要使用一种方法,而在其他情况下,我们需要使用另一种方法。
  • @FreeNickname 感谢您指出这一点。我想我错了那些时间什么时候开始。我只是想解释一下“自启动”在这里的含义。现在到第二点,我不确定这一点,但据我所知,这两种方法都返回相同类型的时间戳。如果你想让它像 UNIX 一样,你可以这样做 (timeInNanos/1000000)
  • 这是我关心的问题:时间戳是一个时间戳。计时器没有“启动”。时间戳只是自某个参考点以来的 (mili|micro|nano) 秒数。从文档中并不清楚,我们应该为ScanResult#timestamp 使用哪个参考点:nanoTimeelapsedRealtimeNanos。也可能是实现在某个时候从一个参考点更改为另一个参考点(不过,我不记得我现在是从哪里得到的)。
猜你喜欢
  • 1970-01-01
  • 2019-08-23
  • 2017-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-09
  • 1970-01-01
相关资源
最近更新 更多