该按键值硬件(驱动)层已支持上报。
硬件(驱动)层到应用层的转化,这层可以理解为SCANCODE->KEYCODE的转化。
在代码中,打印Keyevent.toString,能看得到scanCode值,如果keyCode= UNKNOW值,便说明了硬件(驱动)层到应用层还没有完成。
KeyEvent { action=ACTION_UP, keyCode=KEYCODE_VOLUME_DOWN, scanCode=114, metaState=0, flags=0xc, repeatCount=0, eventTime=7488809, downTime=7488760, deviceId=3, source=0x701 }
对于scanCode的定议一般在framework/base/data/keyboards/Generic.kl
key 114 VOLUME_DOWN WAKE_DROPPED
key 115 VOLUME_UP WAKE_DROPPED
格式 key scanCode keyName ,最后这个貌似可加可不加(具体还有待验证,WAKE_DROPPED 是指设备睡眠时,按下此按键会唤醒设备,但是该key消息不会发送给应用,而WAKE 一样会唤醒设备且key消息会发送给应用)
转化时,会通过scanCode 找到keyCodeName,再通过keyCodeName 去转化成keyCode,而后面一层的定义在
frameworks/native/include/input/InputEventLabels.h
static const InputEventLabel KEYCODES[] = {
// NOTE: If you add a new keycode here you must also add it to several other files.
// Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
DEFINE_KEYCODE(UNKNOWN),
DEFINE_KEYCODE(SOFT_LEFT),
DEFINE_KEYCODE(SOFT_RIGHT),
DEFINE_KEYCODE(HOME),
DEFINE_KEYCODE(BACK),
……
DEFINE_KEYCODE(VOLUME_UP),
DEFINE_KEYCODE(VOLUME_DOWN),
……
{ NULL, 0 }
};
在数组后面加上新的key。不在要中间添加,保待在队尾添加。
到了这里,后面的事情就很简单了,因为你会看到这边有个很好的提醒,提醒我们去KeyEvent.java添加新的key值
frameworks/base/core/java/android/view/KeyEvent.java
public static final int KEYCODE_VOLUME_DOWN = 25;
public static final int KEYCODE_POWER = 26;
……
private static final int LAST_KEYCODE = KEYCODE_HELP;
// NOTE: If you add a new keycode here you must also add it to:
// isSystem()
// isWakeKey()
// frameworks/native/include/android/keycodes.h
// frameworks/native/include/input/InputEventLabels.h
// frameworks/base/core/res/res/values/attrs.xml
// emulator?
// LAST_KEYCODE
建议在队尾添keycode的定义,且递增,这个我们后面再说.
这边的NOTE也很好我帮我们把需要的修改都提到了。
因为我们是在队尾添加的,所以需要将LAST_KEYCODE指向最后的key。
接着是两个方法isSystem()和isWakeKey();
这两个是根据你的需求来解决是否添加,具体也待定。
InputEventLabels.h我们在上面已经修改过了。
frameworks/native/include/android/keycodes.h
/*
* Key codes.
*/
enum {
AKEYCODE_UNKNOWN = 0,
AKEYCODE_SOFT_LEFT = 1,
AKEYCODE_SOFT_RIGHT = 2,
……
AKEYCODE_VOLUME_UP = 24,
AKEYCODE_VOLUME_DOWN = 25,
……
// NOTE: If you add a new keycode here you must also add it to several other files.
// Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
};
一样在队尾添加key的定义
frameworks/base/core/res/res/values/attrs.xml
……
……
到此,已基本完成了。
接着我们来说为什么key要在队尾加,且递增。这个并不是强制性要求,至少还没看到哪里有强制性的说明。如果跳着增加,如当前最大的key值为259,下一个我就定为300,400也可以,并没有什么异常。
其实也就是一个小小提示问题。
打印KeyEvent时,可以看到keyCode 已转成 keyName,我们更好辨认。而不是纯粹的数字。
KeyEvent { action=ACTION_UP, keyCode=KEYCODE_VOLUME_DOWN, scanCode=114, metaState=0, flags=0xc, repeatCount=0, eventTime=7488809, downTime=7488760, deviceId=3, source=0x701 }
而小问题就出现在这里,如果你跳着增加,keyCode 就是直接的数字了,因为他找不到对应用keyName.
@Override
public String toString() {
StringBuilder msg = new StringBuilder();
msg.append("KeyEvent { action=").append(actionToString(mAction));
msg.append(", keyCode=").append(keyCodeToString(mKeyCode));
msg.append(", scanCode=").append(mScanCode);
if (mCharacters != null) {
msg.append(", characters=\"").append(mCharacters).append("\"");
}
msg.append(", metaState=").append(metaStateToString(mMetaState));
msg.append(", flags=0x").append(Integer.toHexString(mFlags));
msg.append(", repeatCount=").append(mRepeatCount);
msg.append(", eventTime=").append(mEventTime);
msg.append(", downTime=").append(mDownTime);
msg.append(", deviceId=").append(mDeviceId);
msg.append(", source=0x").append(Integer.toHexString(mSource));
msg.append(" }");
return msg.toString();
}
keyCodeToString
public static String keyCodeToString(int keyCode) {
String symbolicName = nativeKeyCodeToString(keyCode);
return symbolicName != null ? LABEL_PREFIX + symbolicName : Integer.toString(keyCode);
}
nativeKeyCodeToString找不到时,就会直接打印keyCode了。
这里的原理很简单,上面添加keyCode时,我们会发现都是数组这样的储存方式,也就是说keyCode相当于你的inde值,你将keyCode跳着写,那index自然找不到了,数组越界面。
看下代码
nativeKeyCodeToString的实现在framework/base/core/jni/android_view_KeyEvent.cpp
static jstring android_view_KeyEvent_nativeKeyCodeToString(JNIEnv* env, jobject clazz,
jint keyCode) {
return env->NewStringUTF(KeyEvent::getLabel(keyCode));
}
getLable方法在framework/native/libs/input/input.cpp
const char* KeyEvent::getLabel(int32_t keyCode) {
return getLabelByKeyCode(keyCode);
}
最后来到frameworks/native/include/input/InputEventLabels.h
static const char* getLabelByKeyCode(int32_t keyCode) {
if (keyCode >= 0 && keyCode < size(KEYCODES)) {
return KEYCODES[keyCode].literal;
}
return NULL;
}
没错,这个就是我们刚才添加定义的数组。而keyCode相当于index。将keyCode跳着写,会导致keyCode无法转成相应用keyName。
问题不算大,但是也算多一点了解了系统。