下面为项目中实际运用成功案例
// NOTE: If you add a new keycode here you must also add it to:
// isSystem()
// native/include/android/keycodes.h
// frameworks/base/include/ui/KeycodeLabels.h
// external/webkit/WebKit/android/plugins/ANPKeyCodes.h
// frameworks/base/core/res/res/values/attrs.xml
// emulator?
// LAST_KEYCODE
// KEYCODE_SYMBOLIC_NAMES
//
// Also Android currently does not reserve code ranges for vendor-
// specific key codes. If you have new key codes to have, you
// MUST contribute a patch to the open source project to define
// those new codes. This is intended to maintain a consistent
// set of key code definitions across all Android devices.
上面为主要的大纲主旨,下面实例增加一个硬按键
KeycodeLabels.h
{"SHORTCUT_1", 140},
attrs.xml
<enum name="KEYCODE_SHORTCUT_1" value="140" />
native/include/android/keycodes.h是否需要加入:
AKEYCODE_SHORTCUT_1 = 140,
KeyEvent
public static final int KEYCODE_SHORTCUT_1 = 140;
device目录下找到项目的.mk文件,找到.kl文件,原生态是qwerty.kl,但是因为定制可能有的会自我重新 搞个.kl文件,增加如下:
key 129 SHORTCUT_1 WAKE_DROPPED
说明: 这里的SHORTCUT_1就是我们定义的android键值的字符形式,129则是linux键值
在EventHub.cpp中加载并解析这个map:.kl,那么得到的是linux键值129为key的string,这个string就是SHORTCUT_1,有了KeycodeLabels.h这个KEYCODES数组,就可以获得它对应的android键值了。
KeyPolicyImpl实现
public boolean interceptKeyBeforeDispatching(WindowState win, int action, int flags,
int keyCode, int scanCode, int metaState, int repeatCount, int policyFlags) {
上面方法里面进行判断是否为SHORTCUT_1
if ((keyCode == KeyEvent.KEYCODE_SHORTCUT_1) && !down) {
Log.i(TAG, "coming check down shortcut");
mHandler.removeCallbacks(mShortCutLongPress);
}
其mShortCutLongPress主要进行广播通知
Runnable mShortCutLongPress = new Runnable() {
public void run() {
Log.d(TAG, "long mShortCutPress click shortCut");
mShortCutPressed = false;
Intent intent = new Intent(IntentHelper.ACTION_SHORTCUT);
mContext.sendBroadcast(intent);
}
};
上面mShortCutLongPress里面涉及到一个变量mShortCutPressed = false;是全局的
上面的
interceptKeyBeforeDispatching
上面面里面紧接着实现下面两个逻辑:
if (mShortCutPressed) {
Log.i(TAG ," shortcut shortclick");
if (keyCode == KeyEvent.KEYCODE_DLS_SHORTCUT_1) {
mShortCutPressed = false;
if (!down) {
Log.i(TAG, "down is fals shortcut");
Intent intent = new Intent(IntentHelper.ACTION_RADIO_SHORTCUT);
mContext.sendBroadcast(intent);
}
}
return false;
}
else if (keyCode == KeyEvent.KEYCODE_SHORTCUT_1) {
if(DEBUG)
Log.d(TAG,"PhoneWindowManager->KEYCODE_SHORTCUT_1!!");
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) {
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]) {
return true;
}
}
}
if (down && repeatCount == 0) {
if (!keyguardOn) {
Log.i(TAG, "coming in KeyEvent.KEYCODE_SHORTCUT");
setKeyCode(keyCode);
mHandler.postDelayed(mShortCutLongPress,
ViewConfiguration.getGlobalActionKeyTimeout());
}
mShortCutPressed = true;
}
return true;
} else if ......
对于按键事件的处理一般如下文件中
PhoneWindowManager.java
PhoneWindow.java
添加新的按键过程中可能出现的问题
1.按键框架层中相关变量都添加后,keycode=0.
<1>确保驱动上报键值的准确性。
<1>确保确定设备的kl文件。根据 /system/usr/idc 中的idc 文件,以及 在EventHub.cpp中打印 设备的配置 文件,确定设备的kl 文件,设备不止一个kl文件
<3> kl 文件的键值映射正确。
key 123 KEYCODENAME, KEYCODENAME 与驱动没有关系,必须保证这个 keycode 被添加成功。在KeyEvent.java 中的注释中已经说明了用户添加一个新的按键所需要修改的所有文件。
<4> 框架层修改完成后,为了确保正确,将ap侧代码全部编译一遍,重新烧录system.img.在PhoneWindowManager 中验证按键是否正常。
有关:/frameworks/base/libs/ui/Input.cpp,我不理解什么是系统按键,比如我们车载上的远程按键能是系统按键吗?后来请教老王帮我解释了下:
有些耳机上有两个按键为音乐的上一首下一首的按键值,这些是android系统自带的,我们为了兼容第三方这些值都不能删,而可以往里面加没事
bool KeyEvent::isSystemKey(int32_t keyCode) {
switch (keyCode) {
case AKEYCODE_MENU:
case AKEYCODE_SOFT_RIGHT:
case AKEYCODE_HOME:
case AKEYCODE_BACK:
case AKEYCODE_CALL:
case AKEYCODE_ENDCALL:
case AKEYCODE_VOLUME_UP:
case AKEYCODE_VOLUME_DOWN:
case AKEYCODE_VOLUME_MUTE:
case AKEYCODE_MUTE:
case AKEYCODE_POWER:
case AKEYCODE_HEADSETHOOK:
case AKEYCODE_MEDIA_PLAY:
case AKEYCODE_MEDIA_PAUSE:
case AKEYCODE_MEDIA_PLAY_PAUSE:
case AKEYCODE_MEDIA_STOP:
case AKEYCODE_MEDIA_NEXT:
case AKEYCODE_MEDIA_PREVIOUS:
case AKEYCODE_MEDIA_REWIND:
case AKEYCODE_MEDIA_RECORD:
case AKEYCODE_MEDIA_FAST_FORWARD:
case AKEYCODE_CAMERA:
case AKEYCODE_FOCUS:
case AKEYCODE_SEARCH:
return true;
}
return false;
}
bool KeyEvent::isSystemKey() const {
return isSystemKey(getKeyCode());
}