android4.0 中如何在app 中屏蔽HOME鍵

 近日在研究一個視頻鎖的功能,即在 視頻播放界面上設一個鎖的功能,當該鎖起效後,就會屏蔽back, home, menu三個鍵的功能。

back 和 menu 鍵都可以通過 app層  的 onKeyDown 和 onKeyUp 函數來攔截。但是 home 鍵不行。

於是上網查瞭一下在app層屏蔽 home 鍵的方法。

主流的方法如下所示。但隻在2.2,2.3平臺下有效。(下面列舉的方法隻在android 2.2, 2.3 上有效)

屏蔽Activity, Dialog風格Activity, AlertDialog的Home鍵功能方法分別是:

1.屏蔽Activity中的Home鍵功能,隻需要在你要屏蔽的activity 中重寫 onAttachToWindow() 這個函數就可以瞭

[java]
@Override   
public void onAttachedToWindow() {   
    this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD);    
    super.onAttachedToWindow();   
}   
    @Override 
    public void onAttachedToWindow() { 
        this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD);  
        super.onAttachedToWindow(); 
    }  

 

2.屏蔽 Dialog風格Activity的Home鍵功能,也需要在你要屏蔽的activity 中重寫 onAttachToWindow() 這個函數,但設置window 的值需要改變為 TYPE_KEYGUARD_DIALOG

[java]
@Override   
public void onAttachedToWindow() {   
    this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);  
    super.onAttachedToWindow();   
}   
    @Override 
    public void onAttachedToWindow() { 
        this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
        super.onAttachedToWindow(); 
    } 
 

這裡之所以和Activity區分,是因為Dialog風格Activity如果用第一種方法,這個Dialog風格Activity的背景就變成黑色的,而不是透明的.

3.屏蔽AlertDialog的Home鍵功能

[java]
AlertDialog d = b.create(); 
d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 
    AlertDialog d = b.create();
    d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);

後面通過上面一篇文章的思路來看 4.0平臺的 framework 層的代碼,發現在 PhoneWindowManager.java 的 interceptKeyBeforeDispatching 函數中對home鍵的處理如下:

[java]
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 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 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; 
            } 
        } 
         
        final int flag = attrs.flags; 
 
        if ((flag & WindowManager.LayoutParams.FLAG_HOMEKEY_DISPATCHED) != 0) { 
            // the window wants to handle the home key, so dispatch it to it.  
            return 0; 
        }                 
    } 
     
    return -1; 
        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 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 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;
                    }
                }
               
                final int flag = attrs.flags;
    
                if ((flag & WindowManager.LayoutParams.FLAG_HOMEKEY_DISPATCHED) != 0) {
                    // the window wants to handle the home key, so dispatch it to it.
                    return 0;
                }               
            }
           
            return -1;
     }
       

 
 

在此函數中,如果返回 0,則 home 鍵會交給 app 來處理,如果返回 -1 ,則不會處理 home 鍵。

在app 的你要屏蔽home 鍵的activity 中,隻需要添加該標志就可以瞭

getWindow().addFlags(WindowManager.LayoutParams.FLAG_HOMEKEY_DISPATCHED);

如果要使home 鍵有效,再 clearFlags 即可。

getWindow().clearFlags(WindowManager.LayoutParams.FLAG_HOMEKEY_DISPATCHED);

 

從上面的代碼來看,應該設置 window 的類型也是有效的,但不知為何在 4.0 中不取作用,打Log 看也不取效。不知何故。

this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD);

 作者:fulinwsuafcie
 

發佈留言