实现:扫码获取数据,通过模拟按键上报的方式展示。记录下模拟按键上报的流程实现
文章目录
1.按键KeyCode值与字符映射关系
我们在键盘上输入的都是字符,在Android应用程序层,主要使用按键码keycode来区分,字符和按键码keycode有一个对应关系。
- 源码位置:frameworks/base/core/java/android/view/KeyEvent.java(frameworks/native/include/android/keycodes.h)
...
/** '0' key. */
KEYCODE_0 = 7,
/** '1' key. */
KEYCODE_1 = 8,
/** '2' key. */
KEYCODE_2 = 9,
...
/** 'A' key. */
KEYCODE_A = 29,
/** 'B' key. */
KEYCODE_B = 30,
/** 'C' key. */
KEYCODE_C = 31,
...
贴出部分对应关系。
2.字符转换整数的KeyCode
- 源码位置:frameworks/base/core/java/android/view/KeyCharacterMap.java
KeyCharacterMap用于将按键的码映射为文本可识别的字符串(例如,显示的标签等)。KeyCharacterMap是一个辅助的功能:由于按键码只是一个与UI无关整数,通常用程序对其进行捕获处理,然而如果将按键事件转换为用户可见的内容,就需要经过这个层次的转换了。
现在测试一下:
String testStr = "abc";
char[] charOfUartCode = testStr .toCharArray();
KeyCharacterMap kcm = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
KeyEvent[] keyEvents = kcm .getEvents(charOfUartCode);
for (int i = 0; i < keyEvents.length; i++) {
Log.d("1111", " str --> char :"+keyEvents.length+" "+keyEvents[i].getKeyCode());
}
字符串小写log输出: testStr = “abc”
D/1111: str --> char :10 29
D/1111: str --> char :10 29
D/1111: str --> char :10 30
D/1111: str --> char :10 30
D/1111: str --> char :10 31
D/1111: str --> char :10 31
字符串大写log输出:testStr = “ABC”
D/1111: str --> char :20 59
D/1111: str --> char :20 29
D/1111: str --> char :20 29
D/1111: str --> char :20 59
D/1111: str --> char :20 59
D/1111: str --> char :20 30
D/1111: str --> char :20 30
D/1111: str --> char :20 59
D/1111: str --> char :20 59
D/1111: str --> char :20 31
D/1111: str --> char :20 31
D/1111: str --> char :20 59
整理后的逻辑:
String testStr = "123aBc";
char[] charOfUartCode = testStr .toCharArray();
KeyCharacterMap kcm = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
KeyEvent[] keyEvents = kcm .getEvents(charOfUartCode);
KeyEvent[] mapToUseEvents = new KeyEvent[charOfUartCode.length];
int[] metaStates = new int[charOfUartCode.length];
int eventIndex = 0;
for (int charIndex = 0; charIndex < charOfUartCode.length; charIndex++) {
if((charOfUartCode[charIndex] >= 'A') && charOfUartCode[charIndex] <= 'Z') { // 判断大小写
eventIndex = eventIndex+4;
mapToUseEvents[charIndex] = keyEvents[eventIndex - 3];
metaStates[charIndex] = 1; // 模拟按键上报 大写标志
} else {
mapToUseEvents[charIndex] = keyEvents[eventIndex];
eventIndex = eventIndex+2;
metaStates[charIndex] = 0; // 模拟按键上报 小写标志
}
int curKeyCode = mapToUseEvents[charIndex].getKeyCode();
Log.d("1111", " str --> char :"+keyEvents.length+" "+curKeyCode);
}
eventIndex = 0;
整理后的log输出:testStr = “012aBc”
D/1111: str --> char :14 7
D/1111: str --> char :14 8
D/1111: str --> char :14 9
D/1111: str --> char :14 29
D/1111: str --> char :14 30
D/1111: str --> char :14 31
3.instrumentation模拟按键上报
什么是meta Keys:就是ALT、SHIFT、CAPS_LOCK。
第一列:keycode,由kernel层发出,经*.kl键盘映射文件得到keycode;
- base列:META_KEY没有被激活时的状态,即metaState = 0时映射的字符;
- caps列:是SHIFT或CAPS_LOCK被激活时的状态,此时metaState = 1时映射的字符;
- fn列: ALT被激活,对应metaState = 2时映射的字符;
- caps_fn列:ALT,SHIFT或CAPS_LOCK同时被激活时映射的字符;此时metaState = 3;
所以字母大写时,可以将metaState值设为1,如上。
方法一:不区分字母大小写可以使用直接使用Instrumentation.sendKeyDownUpSync(keycode);
/**
* Sends an up and down key event sync to the currently focused window.
* @param key The integer keycode for the event.
*/
public void sendKeyDownUpSync(int key) {
sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, key));
sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, key));
}
方法二:区分大小写使用Instrumentation.sendKeySync(),只是KeyEvent要添加MetaState参数
/**
* metaState Flags indicating which meta keys are currently pressed.
* /
instrumentation.sendKeySync(new KeyEvent(0,0,KeyEvent.ACTION_DOWN,keycode,0,metaState));
instrumentation.sendKeySync(new KeyEvent(0,0,KeyEvent.ACTION_UP,keycode,0,metaState));
方法三:直接发送字符串
Instrumentation instrumentation = new Instrumentation();
instrumentation.sendStringSync("012aBc"+"\n");
使用Instrumentation要重新开线程。
4.使用InputConnection发送一个KeyeEvent
- 源码位置:frameworks/base/core/java/android/view/inputmethod/InputConnection.java
inputConnection.sendKeyEvent(KeyEvent event);
5.使用IInputContext发送一个KeyeEvent
- 源码位置:frameworks/base/core/java/com/android/internal/view/IInputContext.aidl
IInputContext.sendKeyEvent(KeyEvent event);