http://blog.csdn.net/linweig/article/details/6205142
Android上的home鍵是系統直接處理的,功能如下:
1:跳轉到Home介面,如果Home進程死掉了,則重新啟動Home進程
2:長按5s,彈出選擇應用的視窗,可以切換應用.
由於需要,我需要修改這裡的部分邏輯,修改後的邏輯不能放出,這裡放出我找到的大概地點
view plaincopy to clipboardprint?
public boolean interceptKeyTi(WindowState win, int code, int metaKeys, boolean down,
int repeatCount, int flags) {
boolean keyguardOn = keyguardOn();
if (false) {
Log.d(TAG, "interceptKeyTi code=" + code + " down=" + down + " repeatCount="
+ repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed);
}
// Clear a pending HOME longpress if the user releases Home
// TODO: This could probably be inside the next bit of logic, but that code
// turned out to be a bit fragile so I'm doing it here explicitly, for now.
if ((code == KeyEvent.KEYCODE_HOME) && !down) {
mHandler.removeCallbacks(mHomeLongPress);
}
// If the HOME button is currently being held, then we do special
// chording with it.
if (mHomePressed) {
// If we have released the home key, and didn't do anything else
// while it was pressed, then it is time to go home!
if (code == KeyEvent.KEYCODE_HOME) {
if (!down) {
mHomePressed = false;
if ((flags&KeyEvent.FLAG_CANCELED) == 0) {
// If an incoming call is ringing, HOME is totally disabled.
// (The user is already on the InCallScreen at this point,
// and his ONLY options are to answer or reject the call.)
boolean incomingRinging = false;
try {
ITelephony phoneServ = getPhoneInterface();
if (phoneServ != null) {
incomingRinging = phoneServ.isRinging();
} else {
Log.w(TAG, "Unable to find ITelephony interface");
}
} catch (RemoteException ex) {
Log.w(TAG, "RemoteException from getPhoneInterface()", ex);
}
if (incomingRinging) {
Log.i(TAG, "Ignoring HOME; there's a ringing incoming call.");
} else {
launchHomeFromHotKey();
}
} else {
Log.i(TAG, "Ignoring HOME; event canceled.");
}
}
}
return true;
}
// First we always handle the home key here, so applications
// can never break it, although if keyguard is on, we do let
// it handle it, because that gives us the correct 5 second
// timeout.
if (code == KeyEvent.KEYCODE_HOME) {
// If a system window has focus, then it doesn't make sense
// right now to interact with applications.
WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
if (attrs != null) {
final int type = attrs.type;
if (type == WindowManager.LayoutParams.TYPE_KEYGUARD
|| type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) {
// the "app" is keyguard, so give it the key
return false;
}
final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
for (int i=0; i<typeCount; i++) {
if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
// don't do anything, but also don't pass it to the app
return true;
}
}
}
if (down && repeatCount == 0) {
if (!keyguardOn) {
mHandler.postDelayed(mHomeLongPress, ViewConfiguration.getGlobalActionKeyTimeout());
}
mHomePressed = true;
}
return true;
}
public boolean interceptKeyTi(WindowState win, int code, int metaKeys, boolean down,
int repeatCount, int flags) {
boolean keyguardOn = keyguardOn();
if (false) {
Log.d(TAG, "interceptKeyTi code=" + code + " down=" + down + " repeatCount="
+ repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed);
}
// Clear a pending HOME longpress if the user releases Home
// TODO: This could probably be inside the next bit of logic, but that code
// turned out to be a bit fragile so I'm doing it here explicitly, for now.
if ((code == KeyEvent.KEYCODE_HOME) && !down) {
mHandler.removeCallbacks(mHomeLongPress);
}
// If the HOME button is currently being held, then we do special
// chording with it.
if (mHomePressed) {
// If we have released the home key, and didn't do anything else
// while it was pressed, then it is time to go home!
if (code == KeyEvent.KEYCODE_HOME) {
if (!down) {
mHomePressed = false;
if ((flags&KeyEvent.FLAG_CANCELED) == 0) {
// If an incoming call is ringing, HOME is totally disabled.
// (The user is already on the InCallScreen at this point,
// and his ONLY options are to answer or reject the call.)
boolean incomingRinging = false;
try {
ITelephony phoneServ = getPhoneInterface();
if (phoneServ != null) {
incomingRinging = phoneServ.isRinging();
} else {
Log.w(TAG, "Unable to find ITelephony interface");
}
} catch (RemoteException ex) {
Log.w(TAG, "RemoteException from getPhoneInterface()", ex);
}
if (incomingRinging) {
Log.i(TAG, "Ignoring HOME; there's a ringing incoming call.");
} else {
launchHomeFromHotKey();
}
} else {
Log.i(TAG, "Ignoring HOME; event canceled.");
}
}
}
return true;
}
// First we always handle the home key here, so applications
// can never break it, although if keyguard is on, we do let
// it handle it, because that gives us the correct 5 second
// timeout.
if (code == KeyEvent.KEYCODE_HOME) {
// If a system window has focus, then it doesn't make sense
// right now to interact with applications.
WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
if (attrs != null) {
final int type = attrs.type;
if (type == WindowManager.LayoutParams.TYPE_KEYGUARD
|| type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) {
// the "app" is keyguard, so give it the key
return false;
}
final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
for (int i=0; i<typeCount; i++) {
if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
// don't do anything, but also don't pass it to the app
return true;
}
}
}
if (down && repeatCount == 0) {
if (!keyguardOn) {
mHandler.postDelayed(mHomeLongPress, ViewConfiguration.getGlobalActionKeyTimeout());
}
mHomePressed = true;
}
return true;
}
這裡貼出一些代碼,是在 frameworks/policies/base/phone/com/android/internal/policy/impl/PhoneWindowManager.Java 文包括件裡的,主要是處理特殊按鍵的,裡面涵蓋來android中的特殊按鍵,還包括Search和其他特殊鍵
對於Home鍵的邏輯,大致的分析是:
1 : 如果使用者按下Home鍵,則開始一個計時器,具體是裡面的mHomeLongPress對象,如果超過5s,則彈出一個切換app的視窗
2 : 使用者鬆開Home鍵,則視為單機時間,現把系統中的一些浮動的模態視窗關閉,具體的代碼是 :
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
3: 關閉模態視窗後,啟動或者切換Home應用,代碼:
startDockOrHome
我自己添加的代碼這裡不能放出,有這樣的需求可以在這裏手動加入.