8


1

Androidのシステムクロックを変更すると、タイマーが停止します。 どうすれば再起動できますか?

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には、現在実行されているかどうかを確認する方法がないため、いつ再スケジュールするかわかりません。 何か案は?

1 Answer


4


これを行うにはいくつかの方法があると思います。 どちらの場合もタイマーを使用しません。

ハンドラーを使用して、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で遅延レートを調整することもできます。 別のルーパーを作成する限り、この方法は半予測可能です。 メインスレッドの使用は、タスクが何であるかに応じて適切な場合と適切でない場合があります。

また、AlarmManagerもあります。これは、Contextインターフェイスを介してアクセスできます。これは、より正確な間隔でタスクを繰り返し実行するためのものです。 使用するのはもう少し複雑ですが、RTCと持続性のある反復可能なタスクを使用できる柔軟性が得られます。

AlarmManager manager = mContext.getSystemService(Context.ALARM_SERVICE);
manager.setRepeating(AlarmManager.RTC,
    ,
    ,
    pendingIntent);

たとえば、保留中のインテントは、他の場所で聞くことができるブロードキャストインテントを起動できます。 カスタムオブジェクトのonCreateでこのpendingintentを作成し、onTerminate()でインテントをキャンセルできます。