[英]System.nanoTime() gives wrong times in Android
I am developing a game where some events happen after some predetermined amounts of time. 我正在开发一种游戏,其中一些事件发生在一段预定的时间之后。 For that I need to calculate how much time has elapsed from the starting of the game.
为此,我需要计算从游戏开始经过的时间。 I do that by launching a thread in the main loop and computing the time elapsed with System.nanoTime() .
我这样做是通过在主循环中启动一个线程并使用System.nanoTime()计算经过的时间。
I have tested the code on my smartphone and it works pretty well as long as I do not press the sleep button putting the phone in sleep (which triggers the onpause() method of the activity). 我已经在智能手机上测试了代码,只要我没有按下睡眠按钮将手机置于睡眠状态(触发活动的onpause()方法) , 它就可以正常工作 。 But sometimes when I press the sleep button some very strange things: it seems that System.nanoTime() gives times greater than they actually are (never smaller by the way).
但有时当我按下睡眠按钮时会出现一些非常奇怪的事情:似乎System.nanoTime()给出的时间比它们实际上要大(顺便说一下,从不小)。
I have tried using System.currentTimeMillis() in place of System.nanoTime() but things are even worse (I know that there was some issues with System.nanoTime() on Windows systems with multi-core devices; by the way my smartphone is also multi-core). 我已经尝试使用System.currentTimeMillis()代替System.nanoTime()但事情更糟(我知道在具有多核设备的Windows系统上System.nanoTime()存在一些问题;顺便说一下我的智能手机也是多核的)。
Here is the code: 这是代码:
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
public class MainActivity extends Activity implements Runnable {
private Thread gameThread = null;
private volatile boolean running = false;
private long startTime;
private long totalTime;
private boolean[] afterNSeconds = new boolean[11];
private static long oneBillion = 1000000000;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView tv = new TextView(getApplicationContext());
tv.setText("Start");
setContentView(tv);
}
@Override
public void onResume() {
super.onResume();
running = true;
gameThread = new Thread(this);
gameThread.start();
}
@Override
public void onPause() {
super.onPause();
totalTime = System.nanoTime() - startTime;
running = false;
while (true) {
try {
gameThread.join();
return;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public void run() {
startTime = System.nanoTime();
while (running) {
long elapsedTime = totalTime + System.nanoTime()
- startTime;
for (int j = 1; j <= 10; j++) {
if (elapsedTime >= j * oneBillion
&& !afterNSeconds[j]) {
Log.d("MainActivity", j + ": elapsedTime = "
+ elapsedTime );
afterNSeconds[j] = true;
}
}
}
}
}
Here is a normal output when I do not press the sleep button: 当我不按下睡眠按钮时,这是正常输出:
01-07 23:56:40.722: D/MainActivity(26579): 1: elapsedTime = 1021247230
01-07 23:56:41.708: D/MainActivity(26579): 2: elapsedTime = 2007078538
01-07 23:56:42.701: D/MainActivity(26579): 3: elapsedTime = 3000023615
01-07 23:56:43.701: D/MainActivity(26579): 4: elapsedTime = 4000000538
01-07 23:56:44.701: D/MainActivity(26579): 5: elapsedTime = 5000000846
01-07 23:56:45.701: D/MainActivity(26579): 6: elapsedTime = 6000001230
01-07 23:56:46.701: D/MainActivity(26579): 7: elapsedTime = 7000001384
01-07 23:56:47.701: D/MainActivity(26579): 8: elapsedTime = 8000001923
01-07 23:56:48.701: D/MainActivity(26579): 9: elapsedTime = 9000000769
01-07 23:56:49.701: D/MainActivity(26579): 10: elapsedTime = 10000002000
And here is an anomalous output when I pressed the sleep button after 3 seconds and repressed again after some seconds. 当我在3秒钟后按下睡眠按钮并在几秒钟后再次压制时,这是一个异常输出。 (The anomalous behavior is from 4 to 6) As you can see, after less than 4 seconds have passed System.nanoTime() reports 6 seconds instead.
(异常行为从4到6)正如您所看到的,经过不到4秒后, System.nanoTime()报告的时间为6秒。
01-08 00:02:48.645: D/MainActivity(26579): 1: elapsedTime = 1001408231
01-08 00:02:49.644: D/MainActivity(26579): 2: elapsedTime = 2000000615
01-08 00:02:50.644: D/MainActivity(27265): 3: elapsedTime = 3000000539
01-08 00:02:50.802: D/MainActivity(27265): 4: elapsedTime = 6000000462
01-08 00:02:50.802: D/MainActivity(27265): 5: elapsedTime = 6000000462
01-08 00:02:50.802: D/MainActivity(27265): 6: elapsedTime = 6000000462
01-08 00:03:21.358: D/MainActivity(27265): 7: elapsedTime = 7000000770
01-08 00:03:22.358: D/MainActivity(27265): 8: elapsedTime = 8000000539
01-08 00:03:23.358: D/MainActivity(27265): 9: elapsedTime = 9000000154
01-08 00:03:23.730: D/MainActivity(27265): 10: elapsedTime = 10000003847
How can I modify my code to avoid this behavior? 如何修改代码以避免此行为?
SystemClock is the appropriate clock to use on android SystemClock是在android上使用的合适时钟
Specifically SystemClock.elapsedRealtime()
gives the time since the system was booted which (unlike System.currentTimeMillis()
) isn't affected by hour changes/user action and (unlike uptimeMillis()
) includes time in deep sleep 具体来说,
SystemClock.elapsedRealtime()
给出了自系统启动以来的时间(与System.currentTimeMillis()
不同System.currentTimeMillis()
不受小时更改/用户操作的影响,并且(与uptimeMillis()
不同,包括深度睡眠时间)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.