先说结论:所有修改只适用定制系统有系统源码的场景,否则上层App只能监听到HOME按键的广播(而且由于Home键的特殊性,完全可靠的监听同样需要在framework层修改源码),无办法拦截,下面的方法亲自验证过,参考https://blog.csdn.net/u013286571/article/details/50012901了,修改了其中顺序有误的地方
1. 源码修改 com.android.server.wm.WindowManagerService
if (attrs != null) {
//add by sg , 注释掉对参数类型的判断
/* if (win.mAttrs.type != attrs.type) {
throw new IllegalArgumentException(
"Window type can not be changed after the window is added.");
}*/
flagChanges = win.mAttrs.flags ^= attrs.flags;
attrChanges = win.mAttrs.copyFrom(attrs);
if ((attrChanges & (WindowManager.LayoutParams.LAYOUT_CHANGED
| WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) {
win.mLayoutNeeded = true;
}
}
2. 源码修改 com.android.server.policy.PhoneWindowManager
public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags)方法
方法内部添加一个局部变量标志位isGohome,默认为true
final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
final boolean canceled = event.isCanceled();
+ boolean isGohome = true;
找到Home键事件,增加从WindowManager获取参数,这个参数我们会在activity的onAttach方法进行设置,当接受到该参数时,则将标志位isGohome设为false
if (keyCode == KeyEvent.KEYCODE_HOME) {
+ WindowManager.LayoutParams attrs1 = win != null ? win.getAttrs() : null;
+ if (attrs1 != null) {
+ int type1 = attrs1.type;
+ if (type1 == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) {
+ isGohome = false;
+ }
+ }
调用返回桌面方法前根据标志位进行判断,默认没有设置参数的activity就直接返回桌面,配置了WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG的activity就不响应
if(isGohome == true){
handleShortPressOnHome();
}
3. 在app需要拦截的activity
@Override
public void onAttachedToWindow() {
this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
super.onAttachedToWindow();
}