android有关Home按键的TYPE_KEYGUARD作用的仿照及其流程说明



先看到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键写一些自己的业务逻辑,明天我们解决另外三个问题,待续。。。。。。

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

流程说明暂缓一下,针对仿照我先写一下:

一、在应用中运用

@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)) {
        ......
}

android有关Home按键的TYPE_KEYGUARD作用的仿照及其流程说明_第1张图片


二、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,null,application,System,layer,Types)