使用instrumentation模拟按键上报

实现:扫码获取数据,通过模拟按键上报的方式展示。记录下模拟按键上报的流程实现


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);
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值