转载:http://blog.163.com/chuliang_xu/blog/static/2058271582012102125052919/
android4.0之后应用程序无法再获得Home键消息,这样是对滴,但如果想自己写Launcher就得对Home键相关的一些消息进行处理了。
Home消息是在android framwork中处理的,我们找到Home键处理相关的代码 (不想细看的可以直接看最后)frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java 中的
PhoneWindowManager.java interceptKeyBeforeDispatching 函数中有以下内容
// 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 (keyCode == KeyEvent.KEYCODE_HOME) {
// 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 (mHomePressed && !down) {
mHomePressed = false;
if (!canceled) {
// 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 telephonyService = getTelephonyService();
if (telephonyService != null) {
incomingRinging = telephonyService.isRinging(); //是否正好有电话打进来
}
} 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(); //可以看到这里有launchHome,应该是这里通知了Launcher程序,继续往下看
}
} else {
Log.i(TAG, "Ignoring HOME; event canceled.");
}
return -1;
}
// If a system window has focus, then it doesn't make sense
// right now to interact with applications.
//这一段没有看的很明白,不过很明显没有对Home键处理,只是判断了一些情况然后返回了
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 0;
}
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 -1;
}
}
}
if (down) {
if (repeatCount == 0) {
mHomePressed = true;
} else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
if (!keyguardOn) {
handleLongPressOnHome(); //作为长按Home键处理
}
}
}
return -1;
}
现在我们再进入 launchHomeFromHotKey(); 函数看看
/**
* A home key -> launch home action was detected. Take the appropriate action
* given the situation with the keyguard.
*/
void launchHomeFromHotKey() {
if (mKeyguardMediator.isShowingAndNotHidden()) {
// don't launch home if keyguard showing
//这个keyguard不知道是什么东东,反正它启动了就不响应Home键,系统已经处理了,跟Launcher没关系
} else if (!mHideLockScreen && mKeyguardMediator.isInputRestricted()) {
// when in keyguard restricted mode, must first verify unlock
// before launching home
mKeyguardMediator.verifyUnlock(new OnKeyguardExitResult() {
public void onKeyguardExitResult(boolean success) {
if (success) {
try {
ActivityManagerNative.getDefault().stopAppSwitches(); //关闭这个东东
} catch (RemoteException e) {
}
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY); //关闭这个东东
startDockOrHome(); //启动Dock或者Home 很明显这三个函数都很重要 一个一个去看看
}
}
});
} else {
// no keyguard stuff to worry about, just launch home!
//这里跟上面是一样处理的
try {
ActivityManagerNative.getDefault().stopAppSwitches();
} catch (RemoteException e) {
}
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
startDockOrHome();
}
}
进入sendCloseSystemWindows,startDockOrHome两个函数看看
void sendCloseSystemWindows() {
sendCloseSystemWindows(mContext, null);
}
void sendCloseSystemWindows(String reason) {
sendCloseSystemWindows(mContext, reason);
}
static void sendCloseSystemWindows(Context context, String reason) {
if (ActivityManagerNative.isSystemReady()) {
try {
ActivityManagerNative.getDefault().closeSystemDialogs(reason); //又是调用这个了
} catch (RemoteException e) {
}
}
}
void startDockOrHome() {
Intent dock = createHomeDockIntent();
if (dock != null) {
try {
mContext.startActivity(dock); //启动HomeDock这个Dock好像是自定义的主界面,这里就不管了
return;
} catch (ActivityNotFoundException e) {
}
}
mContext.startActivity(mHomeIntent); //启动HomeIntent(其实就是发一个Intent消息到主界面)
}
我们再看看mHomeIntent是怎么定义的
Intent mHomeIntent;
mHomeIntent = new Intent(Intent.ACTION_MAIN, null);
mHomeIntent.addCategory(Intent.CATEGORY_HOME);
mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
Launcher中接受Intent的地方在
Launcher2\Launcher2\src\com\android\launcher2\launcher.java
protected void onNewIntent(Intent intent) {}函数中
这里就不分析了,先试试能不能接受到再说。