更改 Android 系统时钟会停止计时器。我怎样才能重新启动它们?

发布于 2024-09-09 01:26:03 字数 803 浏览 0 评论 0原文

我需要在 Android 应用程序中运行定期任务。我目前使用这样的计时器:

final Handler guiHandler = new Handler();

// the task to run
final Runnable myRunnable = new Runnable() {

    @Override
    public void run() {
        doMyStuff();
    }
};

Timer timer = new Timer();
timer.schedule(new TimerTask() {

    @Override
    public void run() {
        guiHandler.post(myRunnable);
    }
}, 0, 30000); // run every 30 seconds

这正是我所需要的,但有一个问题:如果我更改模拟器或手机上的时间,计时器就会停止运行。这是我更改时间时日志中显示的内容:

D/SystemClock(  331): Setting time of day to sec=1278920137
W/SystemClock(  331): Unable to set rtc to 1278920137: Invalid argument

没有关于计时器被中断的信息,但在系统时钟更改后它显然不再运行。只要应用程序正在运行,我就需要任务一直运行。

如果定时器像这样停止,我该如何重新启动它? Timer 或 TimerTask 上没有方法来检查它当前是否正在运行,因此我不知道何时重新安排它。有什么想法吗?

I need to run a periodic task in an Android application. I currently use a timer like this:

final Handler guiHandler = new Handler();

// the task to run
final Runnable myRunnable = new Runnable() {

    @Override
    public void run() {
        doMyStuff();
    }
};

Timer timer = new Timer();
timer.schedule(new TimerTask() {

    @Override
    public void run() {
        guiHandler.post(myRunnable);
    }
}, 0, 30000); // run every 30 seconds

This does exactly what I need, but there is a problem: if I change the time on the emulator or phone, the timer stops running. This is what appears in the log when I change the time:

D/SystemClock(  331): Setting time of day to sec=1278920137
W/SystemClock(  331): Unable to set rtc to 1278920137: Invalid argument

Nothing about the timer being interrupted, but it clearly doesn't run anymore after the system clock has changed. I need the task to keep running all the time as long as the application is running.

How can I restart the timer if it gets stopped like this? There's no method on the Timer or TimerTask to check whether it's currently running, so I can't know when to reschedule it. Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我的奇迹 2024-09-16 01:26:03

我认为有几种方法可以做到这一点。在任何一种情况下我都不会使用计时器。

您可以使用处理程序在 postDelayed 调用中运行任务。然后,您的任务必须从自身内部向处理程序重新注册自身。

final int ONE_SECOND = 1000; // one second
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
   public void run() {
      ... // do some stuff
      if (expression) {
         handler.postDelayed(this, ONE_SECOND);
      }
   }
}, ONE_SECOND);

这将使任务在您的应用程序处于活动状态时保持运行。您还可以在 Runnable 内的 postDelayed 中调整延迟率。这种方式只要你再做一个Looper,就是半可预测的。使用主线程可能合适也可能不合适,具体取决于任务是什么。

还有一个 AlarmManager,您可以通过 Context 接口访问它,这意味着以更精确的时间间隔重复执行任务。使用起来稍微复杂一些,但您可以灵活地使用 RTC 和持久的可重复任务。

AlarmManager manager = mContext.getSystemService(Context.ALARM_SERVICE);
manager.setRepeating(AlarmManager.RTC, 
    <start_time_millis>, 
    <period_millis>, 
    pendingIntent);

例如,待处理的意图可以触发您可以在其他地方收听的广播意图。您可以在自定义 Application 对象的 onCreate 中创建此待定意图,并在 onTerminate() 中取消该意图。

I think there are a few ways to do this. I wouldn't use the timer in either case.

You can use a handler to run your task in a postDelayed call. Your task would then have to re-register itself with the handler from within itself.

final int ONE_SECOND = 1000; // one second
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
   public void run() {
      ... // do some stuff
      if (expression) {
         handler.postDelayed(this, ONE_SECOND);
      }
   }
}, ONE_SECOND);

This will keep the task running while your app is alive. You can also adjust the delayed rate in the postDelayed within the Runnable. This way is semi predictable as long as you make another Looper. Using the main thread may or may not be appropriate depending on what the task is.

There is also an AlarmManager, that you can gain access to via the Context interface, which is meant for recurring tasks tasks at more precise intervals. It's a little more complex to use but you get the flexibility of having use of the RTC and persisted repeatable tasks.

AlarmManager manager = mContext.getSystemService(Context.ALARM_SERVICE);
manager.setRepeating(AlarmManager.RTC, 
    <start_time_millis>, 
    <period_millis>, 
    pendingIntent);

For example, the pending intent can fire a broadcast intent that you can listen to elsewhere. You can create this pendingintent in the onCreate of your custom Application object and cancel the intent in the onTerminate().

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文