7

我正在远程控制应用程序上编程。其中一项任务是注入角色。我目前使用的代码如下所示:

Instrumentation instr = new Instrumentation();

String str="a";

// basically the same like calling instr.sendStringSync(str);
char[] chars = str.toCharArray();
KeyCharacterMap keyCharacterMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
KeyEvent[] keyEvents = keyCharacterMap.getEvents(chars);
if (keyEvents != null) {
    for (KeyEvent kev : keyEvents) {
        instr.sendKeySync(kev);
    }
}

这对英文字符非常有效(字符显示在 EditText 框中)。但是,如果我尝试注入例如韩语字符,则会失败。即使我配置了韩语和键盘,函数 getEvents 也会返回 null。

我知道还有另一种直接注入字符串的方法:

KeyEvent event = new KeyEvent(SystemClock.uptimeMillis(), str, 0, 0);
instr.sendKeySync(event);

这也不起作用 - EditText 框中没有显示任何字符,并且在我的测试活动中也没有调用 onKeyMultiple()。

这很奇怪,因为具有相同事件的 dispatchKeyEvent() 在我的测试活动中起作用:

KeyEvent event = new KeyEvent(SystemClock.uptimeMillis(), str, 0, 0);
dispatchKeyEvent(event);

无论哪个活动,我的远程控制应用程序都需要注入事件。这可以使用 Instrumentation(带有android.permission.INJECT_EVENTS平台密钥的签名)来实现。

如何使用仪器注入非英文字符?还有另一种方法可以做到这一点吗?例如使用 dispatchKeyEvent (也必须适用于其他活动/应用程序)。

4

2 回答 2

2

我将上面的部分作为额外信息。我找到了解决方案。它需要root,但是如果您可以使用应用程序密钥签名,我想这不是问题。您可以编辑文件 Virtual.kcm (/system/usr/keychars/Virtual.kcm),它是默认的键字符映射 (kcm)。您可以添加任何您想要的字符,然后使用 Instrumentation.sendStringSync(String string) 方法,因为它将能够从新的 kcm 生成 KeyEvents。

我在手机上编辑 kcm 时遇到了一些问题,所以我所做的就是将其复制到计算机上,在那里进行编辑,然后将其复制回设备。

我希望这有帮助!


在此链接中,出现以下内容。无论您在设置上选择什么,虚拟键盘都具有美国 keyCharacterMap 和布局。我一直无法找到解决此问题的方法。

Language Note

Android does not currently support multilingual keyboards. Moreover, the built-in generic key character map assumes a US English keyboard layout.

OEMs are encouraged to provide custom key character maps for their keyboards if they are designed for other languages.

Future versions of Android may provide better support for multilingual keyboards or user-selectable keyboard layouts.
于 2013-03-13T09:54:14.937 回答
-2

您可以将此方法和 InputFilter 用于 EditText:

private boolean isLatinSymbolOrDigit(char c) 
{
    // Allow [a-zA-Z0-9]
    if ('0' <= c && c <= '9')
        return true;
    if ('a' <= c && c <= 'z')
        return true;
    if ('A' <= c && c <= 'Z')
        return true;
    return false;
}

InputFilter filter = new InputFilter() 
{
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) 
    {
        for (int i = start; i < end; i++) 
        {
            if (isLatinSymbolOrDigit(source.charAt(i))) 
            {
            }                   
            else 
            {
                //wrong character
                return "";
            }
        }
        return null;
    }
};

editText.setFilters(new InputFilter[] {filter});
于 2012-11-23T21:46:14.240 回答