先看到PhoneWindowManager中public boolean interceptKeyTi(WindowState win, int code, int metaKeys, boolean down,
int repeatCount, int flags) 这个方法的实现,interceptKeyTi你可以暂时理解为WindowManagerService中处理驱动和上层按键实现的过滤器
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
/* 按键按下 */
public boolean onKeyDown(int keyCode, KeyEvent event)
{
switch (keyCode)
{
case KeyEvent.KEYCODE_HOME:
DisplayToast("HOME键按下");
break;
}
return super.onKeyDown(keyCode, event);
}
/*按键弹起*/
public boolean onKeyUp(int keyCode, KeyEvent event)
{
switch (keyCode)
{
case KeyEvent.KEYCODE_HOME:
DisplayToast("HOME键弹起");
break;
}
return super.onKeyUp(keyCode, event);
}
下面我们来看第一个问题的解答:Activity中有两个可覆盖的方法,都可以做如下的初始化:
/**
* Called when the current {@link Window} of the activity gains or loses
* focus. This is the best indicator of whether this activity is visible
* to the user. The default implementation clears the key tracking
* state, so should always be called.
*
* Note that this provides information about global focus state, which
* is managed independently of activity lifecycles. As such, while focus
* changes will generally have some relation to lifecycle changes (an
* activity that is stopped will not generally get window focus), you
* should not rely on any particular order between the callbacks here and
* those in the other lifecycle methods such as {@link #onResume}.
*
*
As a general rule, however, a resumed activity will have window
* focus... unless it has displayed other dialogs or popups that take
* input focus, in which case the activity itself will not have focus
* when the other windows have it. Likewise, the system may display
* system-level windows (such as the status bar notification panel or
* a system alert) which will temporarily take window input focus without
* pausing the foreground activity.
*
* @param hasFocus Whether the window of this activity has focus.
*
* @see #hasWindowFocus()
* @see #onResume
* @see View#onWindowFocusChanged(boolean)
*/
public void onWindowFocusChanged(boolean hasFocus) {
WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
lp.type = WindowManager.LayoutParams.TYPE_KEYGUARD ;
this.getWindow().setAttributes(lp);
}
/** * Called when the main window associated with the activity has been
* attached to the window manager.
* See {@link View#onAttachedToWindow() View.onAttachedToWindow()}
* for more information.
* @see View#onAttachedToWindow
*/
public void onAttachedToWindow() {
this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD);
super.onAttachedToWindow();
}
onWindowFocusChanged(boolean) 当窗口包含的view获取或失去焦点时触发
onAttachedToWindow() 当view被附着到一个窗口时触发
LayoutParams的构造方式有很多种可以顺带学习下,同时最好学习下它的参数,项目中用到就知道它的重要性了:
public LayoutParams() {
super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
type = TYPE_APPLICATION;
format = PixelFormat.OPAQUE;
}
public LayoutParams(int _type) {
super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
type = _type;
format = PixelFormat.OPAQUE;
}
public LayoutParams(int _type, int _flags) {
super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
type = _type;
flags = _flags;
format = PixelFormat.OPAQUE;
}
public LayoutParams(int _type, int _flags, int _format) {
super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
type = _type;
flags = _flags;
format = _format;
}
public LayoutParams(int w, int h, int _type, int _flags, int _format) {
super(w, h);
type = _type;
flags = _flags;
format = _format;
}
public LayoutParams(int w, int h, int xpos, int ypos, int _type,
int _flags, int _format) {
super(w, h);
x = xpos;
y = ypos;
type = _type;
flags = _flags;
format = _format;
}
到这一步为至即为网上很多转的都一样的帖子即屏蔽Home键写一些自己的业务逻辑,明天我们解决另外三个问题,待续。。。。。。
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
流程说明暂缓一下,针对仿照我先写一下:
一、在应用中运用
@Override
public void onWindowFocusChanged(boolean hasFocus) {
final int stretch = ViewGroup.LayoutParams.FILL_PARENT;
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(stretch,
stretch, WindowManager.LayoutParams.TYPE_KEYGUARD_VUI,
WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN,
PixelFormat.TRANSPARENT);
lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
PoiSearchActivity.this.getWindow().setAttributes(lp);
super.onWindowFocusChanged(hasFocus);
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_MOD) && (event.getRepeatCount() == 0)) {
......
}
二、fromwork层实现
1、PhoneWindowManager.java
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_VUI;
public int windowTypeToLayerLw(int type) {
if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
return APPLICATION_LAYER;
}
switch (type) {
case TYPE_KEYGUARD_VUI:
return KEYGUARD_LAYER;
}
Log.e(TAG, "Unknown window type: " + type);
return APPLICATION_LAYER;
}
public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
switch (attrs.type) {
case TYPE_STATUS_BAR:
if (mStatusBar != null) {
return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
}
mStatusBar = win;
break;
case TYPE_SEARCH_BAR:
if (mSearchBar != null) {
return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
}
mSearchBar = win;
break;
case TYPE_KEYGUARD:
if (mKeyguard != null) {
return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
}
mKeyguard = win;
break;
case TYPE_KEYGUARD_VUI:
if (mKeyguard != null) {
return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
}
mKeyguard = win;
break;
}
return WindowManagerImpl.ADD_OKAY;
}
public boolean interceptKeyTi(WindowState win, int code, int metaKeys, boolean down,
int repeatCount) {
boolean keyguardOn = keyguardOn();
......
if (code == KeyEvent.KEYCODE_HOME) {
......
else if (code == KeyEvent.KEYCODE_MODE/*KeyEvent.KEYCODE_SRC*/) {
//--added by ting.li@1009-2009: do with KEYCODE_SRC Down!
if(DEBUG)
Log.d(TAG,"PhoneWindowManager->KEYCODE_MODE!!");
// 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;
}else if(type == WindowManager.LayoutParams.TYPE_KEYGUARD_VUI)
{
// 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
public static final int TYPE_KEYGUARD_VUI = FIRST_SYSTEM_WINDOW+15;
/** {@inheritDoc} */
public int windowTypeToLayerLw(int type) {
if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
return APPLICATION_LAYER;
}
switch (type) {
.......
case TYPE_KEYGUARD_VUI:
return KEYGUARD_LAYER;
}
Log.e(TAG, "Unknown window type: " + type);
return APPLICATION_LAYER;
}
public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
switch (attrs.type) {
case TYPE_STATUS_BAR:
if (mStatusBar != null) {
return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
}
mStatusBar = win;
break;
case TYPE_SEARCH_BAR:
if (mSearchBar != null) {
return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
}
mSearchBar = win;
break;
case TYPE_KEYGUARD:
if (mKeyguard != null) {
return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
}
mKeyguard = win;
break;
case TYPE_KEYGUARD_VUI:
if (mKeyguard != null) {
return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
}
mKeyguard = win;
break;
}
return WindowManagerImpl.ADD_OKAY;
}