Timer计时任务因系统时间的修改致使挂起解决方案

    以前开发的一款运行在定制Android设备上的一个实时监控程序发生了一个很奇怪的问题:关机状态下放置了半个月左右的时间以后,再次开机使用,使用到一半的时候,显示界面就卡死在某一个状态下了(显示界面只显示一行文字,表明当前的状态)。取到的log信息里没有任何错误信息,测试也很难再现问题(由于条件较难知足,关机状态下放置半个月)。以后就各类查问题......html

    终于找到是Timer的问题:若是在启动一个Timer任务以后,进行了系统时间的修改操做,包括系统自动同步网络时间,都有可能致使这个Timer任务挂起java

    系统时间修改到当前时间以后,不会影响Timer的执行;可是若是系统时间修改到当前时间以前,就会致使Timer挂起。详见博文:“关于Timer运行时修改系统时间”。
网络

    要解决这个问题的话,须要程序在系统时间改变以后主动重启Timer,Android系统在系统时间被修改以后,会发出一条广播:Intent.ACTION_TIME_CHANGED,咱们只须要监听这个广播便可。ide

在onCreate方法或者其它合适的地方注册广播监听方法:测试

IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_DATE_CHANGED);
this.registerReceiver(new TimeChangedReceiver(), filter);

而后实现广播监听器:this

public class TimeChangedReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
	        
        Log.d(TAG, "---onReceive() start!---");

        String action = intent.getAction();

        if (Intent.ACTION_DATE_CHANGED.equals(action)) {
            Log.d(TAG, "---DATE_CHANGED!---");
        }

        if (Intent.ACTION_TIME_CHANGED.equals(action)) {
            mHandlerMsg.sendEmptyMessage(MsgType.RESTARTTIMER);
            Log.d(TAG, "---TIME_CHANGED!---");

        }
	        
        Log.d(TAG, "---onReceive() end!---");
    }

}

具体的Timer重启方法放在了Handle中:spa

final static class MsgType {
    ...
    final static int RESTARTTIMER = 7;
    ...
}
final Handler mHandlerMsg = new Handler(new Handler.Callback() {
...
    @Override
    public boolean handleMessage(Message msg) {
        switch (msg.what) {
        ...
        case MsgType.RESTARTTIMER: {
            try {
                timer.cancel();
            } catch (Exception e) {
                e.printStackTrace();
            }
            timer = null;
            timer = new Timer();
            timer.schedule(new firstTask(), 0, TIMER_INTERVAL);
        }
        break;
        ...
        }
    }
...
}

firstTask代码以下:.net

class firstTask extends TimerTask {
    @Override
    public void run() {
	// TODO do something	
    }
}

经过以上这种方式就能够解决在修改了系统时间后Timer被挂起的问题。code

相关文章
相关标签/搜索