最近在測試上面,有需要在Android上面針對特定功能反覆開關的需求。
本來是想說在原本的原始碼上面讓他定時反覆啟動。
不過這樣每次都要額外加code以及build code,實在是有點麻煩。
所以這邊試著寫一個簡單的APP去定時做這件事情。
不過Android APP嗎,你知道的,如果用一般的delay的話,過一下就ANR了
爬了一下Android framework的做法,後來決定用Handler thread + delay message的方法來做
概念上是宣告一個handler thread,這東西會用一個獨立的thread去聽message。
如果有人對這個handler 送message,handler可以根據不同的message,去做不同的事情。
而利用延遲訊息(delayMessage),可以達到定時去做同一件事情的效果。
這邊筆記一下Handler底下sendEmptyMessage 和sendEmptyMessageDelayed的差異。
sendEmptyMessage
原生宣告是
boolean sendEmptyMessage (int what)。
顧名思義,這個function是送一個空的訊息給Handler
所以不用把東西特別包成Message型態,可以直接送一個int的值
sendEmptyMessageDelayed
原生宣告是
boolean sendEmptyMessageDelayed (int what, long delayMillis)
相較於sendEmptyMessage,他可以決定到底這個message要等多久後再送,單位是ms
下面是一個簡單的範例:
private static final int NEXT_ACTION_INTERVAL_MS = 5000;
...
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG, "onCreate()+");
setContentView(R.layout.main);
context = this;
mWifiManager = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);
mLock = mWifiManager.createMulticastLock(TAG);
mHandler = new Handler(Looper.getMainLooper()) ;
// 宣告一個按鈕,按下去後就會去sendEmptyMessage(CMD_START_TEST)給mThreadHandler
button1 = (Button) findViewById(R.id.button1);
button1.setOnClickListener( new OnClickListener() {
public void onClick(View v) {
mThreadHandler.sendEmptyMessage(CMD_START_TEST);
result_text.setText("Start thread action");
}
});
...
mThread = new HandlerThread("name");
mThread.start();
mThreadHandler = new Handler(mThread.getLooper()) {
private boolean isRunning = false;
private int mCounter = 0;
@Override
public void handleMessage (Message msg) {
super.handleMessage(msg);
switch (msg.what) {
// ** 接到CMD_START_TEST後,除了做特定的事情外。
// ** 並會等候NEXT_ACTION_INTERVAL_MS後再發CMD_LOOP_TEST
case CMD_START_TEST:
if (!isRunning) {
this.sendEmptyMessageDelayed(CMD_LOOP_TEST, NEXT_ACTION_INTERVAL_MS);
isRunning = true;
Log.e(TAG, "Start Testing!");
mWifiManager.startScan();
mCounter++;
result_text.setText("Repeat times: " + mCounter);
}
break;
case CMD_STOP_TEST:
isRunning = false;
mCounter = 0;
break;
// ** 接到CME_LOOP_TEST後,繼續相同的測試&準備下一個NEXT_ACTION_INTERVAL_MS後的message
case CMD_LOOP_TEST:
if (isRunning) {
mWifiManager.startScan();
mCounter++;
result_text.setText("Repeat times: " + mCounter);
this.sendEmptyMessageDelayed(CMD_LOOP_TEST, NEXT_ACTION_INTERVAL_MS);
}
break;
}
}
};