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

相關文章
相關標籤/搜索