6/13/2011

How to capture home key event

在Android 2.3 , 想要取得home key event來做特殊事件 , 應用層是收不到該事件的.

因為Android在framwork layer做掉 , 所以並沒往APP layer上送.

frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java


// First we always handle the home key here, so applications
// can never break it, although if keyguard is on, we do let
// it handle it, because that gives us the correct 5 second
// timeout.
if (keyCode == KeyEvent.KEYCODE_HOME) {
Log.i(TAG,"----2keyCode == 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;
}
.............
.............
}


註釋寫的很清楚 , 而其中的重點在於type , 可以看出它有兩個type來判斷對該事件的處理 :

WindowManager.LayoutParams.TYPE_KEYGUARD
WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG

所以在APP層 , 想要接收home key event的話 , 改變activity的類型即可 :


/* capture home key event*/
@Override
public void onAttachedToWindow()
{
this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
super.onAttachedToWindow();
}


其中的WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG可以改成WindowManager.LayoutParams.TYPE_KEYGUARD

但我測試過 , 用TYPE_KEYGUARD似乎會影響一些View的處理....

==========================

我發現..TYPE_KEYGUARD會使view變成懸浮視窗= =

非常怪異 !! 但實在想不出原因...最後只好自己硬幹 , 如果有人試出問題..別罵我QQ

上面提到定義了這些Typ......所以呢,我就自己定義一組Type !!

首先呢,可以在PhoneWindowManager.Java新增自己的Type :


if(type == WindowManager.LayoutParams.TYPE_DASHBOARD) {
Log.d("DASHBOARD","**** Send the home key event to app ****");
return false;
}


我自己定義了一個叫"TYPE_DASHBOARD"的東東,之後再到framwork/base/core/java/android/view/WindowManager.java去新增 :


@ViewDebug.ExportedProperty(mapping = {
.....
.....
@ViewDebug.IntToString(from = TYPE_DASHBOARD, to = "TYPE_DASHBOARD")
})

---------

public static final int TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15;

/* Send Home key event to app layer */
public static final int TYPE_DASHBOARD = FIRST_SYSTEM_WINDOW+50;


當然了..那個後面數字隨便..50只是我的辛運數字 !!

改其它數字會不會出事就聽天命了...

還沒完 !! 再來到framwork/base/include/ui/InputDispatcher.h新增 :

// Window types from WindowManager.LayoutParams
enum {
.....
.....
TYPE_DASHBOARD = FIRST_SYSTEM_WINDOW+50,
}


到這裡,framwork的地方就改完了,接著只要在自己的APK加上這段 :

/* capture home key event*/
public static final int TYPE_DASHBOARD=2050;
@Override
public void onAttachedToWindow()
{
this.getWindow().setType(TYPE_DASHBOARD);
super.onAttachedToWindow();
}


嘿嘿,這樣接下來只要呼叫dispatchKeyEvent就可以收到Home key事件了 !! 而且不會有任何後遺症了喔 !!