android有关Home按键的TYPE_KEYGUARD作用的仿照及其流程说明
来源:互联网 发布:伦敦陷落 知乎 编辑:程序博客网 时间:2024/04/30 06:41
先看到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<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; } } }
从上面的注释可以看到注释:// the "app" is keyguard, so give it the key ,就是说当在应用界面下的时候,按了HOME键而且当前应用的WindowManager.LayoutParams.type的值是WindowManager.LayoutParams.TYPE_KEYGUARD就让直接返回;返回做什么呢,我先告诉大家,这个interceptKeyTi方法被调用的地方的流程后续步骤就是根据这个interceptKeyTi的返回值来判断,如果返回的是false就让当前应用自己去做HOME键的业务处理通过类似下面的代码
/* 按键按下 */ 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); }
这里就产生了疑问:一、WindowManager.LayoutParams.type的值是在应用的哪里初始化的,二、interceptKeyTi方法被调用的地方的流程后续步骤是怎么调应用的HOME键的处理方式的,三、interceptKeyTi方法被调用的地方的流程后续步骤是怎么获取到WindowManager.LayoutParams.type初始化的值的;这三个疑问基本上就是按键的一个流程即怎么通过底层驱动到Activity相应按键事件相应的。
下面我们来看第一个问题的解答: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. * * <p>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}. * * <p>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键写一些自己的业务逻辑,明天我们解决另外三个问题,待续。。。。。。
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
流程说明暂缓一下,针对仿照我先写一下:
一、在应用中运用
@Overridepublic 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<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) { mModePressed = true; } return true; .......
WindowManager.java
public static final int TYPE_KEYGUARD_VUI = FIRST_SYSTEM_WINDOW+15;
MidWindowManager.java
/** {@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; }
- android有关Home按键的TYPE_KEYGUARD作用的仿照及其流程说明
- Android有关Home按键的TYPE_KEYGUARD作用
- 有关按键的专利
- android 屏保锁中屏掉按键和HOME键的方法
- Android Home按键的监听与屏蔽方式
- Android 4.0中按键的处理流程
- Android 4.0中按键的处理流程
- Android 4.0中按键的处理流程
- Android 4.0中按键的处理流程
- Android 4.0中按键的处理流程
- Android 4.0中按键的处理流程
- Android framework层 按键的处理流程
- Android Activity的按键事件处理流程
- android软件方式模拟硬按键的功能,包括home、back等所有按键
- 关于使用 FLAG_HOMEKEY_DISPATCHED 标志在应用层截获 HOME 按键的说明
- Android 屏蔽 Home 按键
- Android拦截HOME按键
- Android 拦截 HOME 按键
- ContentProvider
- 安装Eclipse时,老提示jvm版本过低,原因和解决办法
- jap的INCLUDE标签与INCLUDE指令FORWARD指令研究
- 同源策略
- 04_Shift_Or
- android有关Home按键的TYPE_KEYGUARD作用的仿照及其流程说明
- 常用设计模式
- GPRS如何有电脑上网(不用蓝牙)
- ContentProvider示例
- Xcode 4.2.* 常用快捷键 + Mac下常用快捷键(带图)
- 黑马程序员——Java IO总结(二)
- Linux下查看文件和文件夹大小
- 查看linux文件目录的大小和文件夹包含的文件数
- C++中的预处理