android4.x在framework的phonewindowmanager對power(keyevent.keycode_power)和home(keyevent.keycode_home)鍵做了處理,不會把這些鍵傳送上層應用程式。如需要把這些鍵發送給activity和service,需要在phonewindowmanager處理這些鍵時“發送一個廣播出去,然後在應用程式接收到廣播後做處理”。
如果應用程式隻需要擷取擷取待機、喚醒、關機、網絡狀态變化消息,則可監聽以下廣播消息:
1) 待機:
廣播消息:android.intent.action.screen_off (代碼)
2) 喚醒:
廣播消息:android.intent.action.screen_on (代碼)
3) 關機:
廣播消息:android.intent.action.action_shutdown (xml或代碼)
4) 網絡狀态變化:
廣播消息:android.net.conn.connectivity_change (xml或代碼)
然後調用下面的isnetworkavailable擷取目前網絡狀态。
public static boolean isnetworkavailable(context context) {
connectivitymanager mgr = (connectivitymanager) context
.getsystemservice(context.connectivity_service);
networkinfo[] info = mgr.getallnetworkinfo();
if (info != null) {
for (int i = 0; i < info.length; i++) {
if (info[i].getstate() == networkinfo.state.connected) {
return true;
}
}
}
return false;
}
短按power鍵處理流程如下圖所示:
長按power鍵處理流程如下圖所示:
如果長按power鍵(超過500ms),則此消息(message.callback為mpowerlongpress)将被執行。mpowerlongpress (phonewindowmanager.java)定義如下:
[java] view
plaincopy
private final runnable mpowerlongpress = new runnable() {
public void run() {
// the context isn't read
if (mlongpressonpowerbehavior < 0) {
mlongpressonpowerbehavior = mcontext.getresources().getinteger(
com.android.internal.r.integer.config_longpressonpowerbehavior);
}
switch (mlongpressonpowerbehavior) {
case long_press_power_nothing:
break;
case long_press_power_global_actions:
mpowerkeyhandled = true;
performhapticfeedbacklw(null, hapticfeedbackconstants.long_press, false);
sendclosesystemwindows(system_dialog_reason_global_actions);
showglobalactionsdialog();
case long_press_power_shut_off:
shutdownthread.shutdown(mcontext, true);
}
};
它是一個匿名内部類,它是一個實作runnable的類的對象引用,是以
new runnable() {
public void run(){
...
}
};
它包括了定義這個類(隻不過這個類沒有名字)和執行個體化這個類的對象。
當逾時時,其執行流程如下圖所示:
reboot系統調用流程如下圖所示:
長按電源鍵:彈出關機确認對話框(keydown之後,如果 500ms之内,沒有收到keyup則彈出關機确認對話框)
短按電源鍵:執行待機(keyup時執行<wmactions=4>)或喚醒(keydown時執行<wmactions=2>)
對于長按電源鍵,在phonewindowmanager.java的interceptkeybeforequeueing函數中進行處理,其相關代碼如下 :
case keyevent.keycode_power: {
result &= ~action_pass_to_user;
if (down) {
if (isscreenon && !mpowerkeytriggered
&& (event.getflags() & keyevent.flag_fallback) == 0) {
mpowerkeytriggered = true;
mpowerkeytime = event.getdowntime();
interceptscreenshotchord();
...
// power key down, set mpowerlongpress executing after 500ms
interceptpowerkeydown(!isscreenon || hungup
|| mvolumedownkeytriggered || mvolumeupkeytriggered);
} else {
mpowerkeytriggered = false;
cancelpendingscreenshotchordaction();
if (interceptpowerkeyup(canceled || mpendingpowerkeyupcanceled)) {
result = (result & ~action_poke_user_activity) | action_go_to_sleep;
// power key up, remove the mpowerlongpress, that is, if user release
// power key during 500ms, mpowerlongpress will not be execute, then execute sleep
mpendingpowerkeyupcanceled = false;
break;
}
private void interceptpowerkeydown(boolean handled) {
mpowerkeyhandled = handled;
if (!handled) {
mhandler.postdelayed(mpowerlongpress, viewconfiguration.getglobalactionkeytimeout()/*500ms*/);
private boolean interceptpowerkeyup(boolean canceled) {
if (!mpowerkeyhandled) {
mhandler.removecallbacks(mpowerlongpress);
return !canceled;
return false;
}