【问题标题】:How to make KeyDown and KeyUp on android device?如何在安卓设备上制作 KeyDown 和 KeyUp?
【发布时间】:2019-06-19 05:33:39
【问题描述】:

我有一个问题。

我正在安卓设备上制作Keystroke dynamics 应用程序。

现在,我使用度量字符串和EditText 创建一个活动。我想在软键盘上捕捉KeyDownKeyUp 事件。

我的问题是,在使用 Java 的 Android 上捕获 KeyUpKeyDown 的最佳方法是什么?如果EditText 是个不错的选择?如果它有方法来捕捉任何按键?

编辑

我想从上面的字符串中检测键并测量按下它的时间,(例如在KeyDown 上开始测量并在KeyUp 上停止)。如果可能的话,我想阻止我的test string 中未提及的其他键(它的 9RJhl6aH0n,就像在我的屏幕中一样)

EDIT2

到目前为止,我所取得的成就是这样的,但是当我编写以下代码行时,我的应用程序在 default 上崩溃了:measureText.setText("")。它工作得很好,但它仍然不会在KeyDown(或KeyPress)上触发。这些方法只在KeyUp 上运行,当用户刚刚输入字母时。顺序很重要!

measureText.addTextChangedListener(new TextWatcher(){
        @Override
        public void afterTextChanged(Editable arg0) {
            switch(measureText.getText().toString()){
                case "9":
                    break;
                case "9R":
                    break;
                case "9RJ":
                    break;
                case "9RJh":
                    break;
                case "9RJhl":
                    break;
                case "9RJhl6":
                    break;
                case "9RJhl6a":
                    break;
                case "9RJhl6a0":
                    break;
                case "9RJhl6a0n":
                    break;
                default:
                    measureText.getText().clear();
                    break;

            }
            return;
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            // TODO Auto-generated method stub
            return;
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {

            return;
        }
    });

【问题讨论】:

  • 您想计时按键吗?还是只检测按键?
  • 我有一个test-string(我添加了我的看法)。我希望用户键入该字符串。我想验证他是否按下了我的test-string 中提到的字符键。当他按下正确的键时,我开始根据stopwatchJava 中的类似内容来测量时间。如果我能阻止机会按下我在帖子中粘贴在屏幕上的 test-string 中没有的键,那就太好了
  • 使用调度事件@michasaucer
  • Android 文档中我找不到在我的情况下使用它的方法
  • 我正在回答我的问题,请看你是否覆盖了这个方法。

标签: java android biometrics


【解决方案1】:

您可以在Activity 中使用dispatchKeyEvent(KeyEvent event)

@Override
public boolean dispatchKeyEvent(KeyEvent event) {
    Log.i("key pressed", String.valueOf(event.getKeyCode()));
    return super.dispatchKeyEvent(event);
}

检测按键

【讨论】:

  • 它是如何工作的?是监听器,监听整个活动还是我需要将该方法附加到我的EditText?如何检测密钥(例如,ShiftAB 等)?正如我在原始帖子中提到的那样,当用户按下并离开确切的键时,我需要开始测量时间
  • 这会监听你的活动
  • 是否有可能检测到我想被检测到的键?以及如何做到这一点?
  • 您可以映射键,并在 KeyEvent 中检测它们是否被点击,例如。
  • 类似KeyEvent event == KeyEvent.KEYCODE_A?我怎么知道,如果按键被按下或离开?我需要更详细的答案,因为函数体并没有告诉我太多
【解决方案2】:

您需要小心地重写以下函数:

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {

    switch (keyCode) {
        case KeyEvent.KEYCODE_A:
        {
            //your Action code
            return true;
        }
    }
    return super.onKeyDown(keyCode, event);
}

对于编辑文本:

mMyEditText.addTextChangedListener(new TextWatcher(){

    public void afterTextChanged(Editable s) 
    {
    }
    public void beforeTextChanged(CharSequence s, int start, int count, int after) 
    {

    }
    public void onTextChanged(CharSequence s, int start, int before, int count) 
    {
    }
);

【讨论】:

  • 谢谢,这些方法与onKeyDown 和其他方法有什么关系?
【解决方案3】:

你只是使用activity的dispatch事件

像这样:

 @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_POINTER_DOWN:
                break;
            case MotionEvent.ACTION_POINTER_UP:
                break;
            case MotionEvent.ACTION_UP:
                break;
            case MotionEvent.ACTION_DOWN:
                break;
        }
            return super.dispatchTouchEvent(ev);
    }

这样,您可以轻松控制 KeyDown 和 KeyUp 事件。

你可以在这里找到所有MotionEvents

对于软键,您只能使用TextChangeListener

    editText.addTextChangedListener(new TextWatcher(){

        @Override
        public void afterTextChanged(Editable arg0) {
            // TODO Auto-generated method stub
  switch (arg0.toString()) {
                    case "9":
                        break;
                    case "9R":
                        break;
                    case "9RJ":
                        break;
                    case "9RJh":
                        break;
                    case "9RJhl":
                        break;
                    case "9RJhl6":
                        break;
                    case "9RJhl6a":
                        break;
                    case "9RJhl6a0":
                        break;
                    case "9RJhl6a0n":
                        break;
                    default:
                        arg0.clear();
                        break;

                }
                return;

        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count,
                int after) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            // here right logic for getting last char and show it on toast

        }

    });  

【讨论】:

  • 什么是动作指针?我想抓住KASHIFT 等键。再次阅读我的原帖
  • 我需要更详细的答案。所以你在屏幕上编码事件?如果用户触摸屏幕,ACTION_DOW 会启动?
  • @michasaucer 是的
  • 有道理。我会在今天或明天检查它。如果它是正确的,我会把你的帖子标记为答案,我会给你赏金
  • @michasaucer 每当用户触摸屏幕时就会触发不同的动作。
【解决方案4】:

我会说,OnKeyUpOnKeyDown 事件不会削减它,因为软键盘几乎不会发出任何这些。这是一个粗略的原型,它根据预期的字符串过滤字符的输入。有很大的改进空间;虽然自定义实现仍然是比尝试使用框架方法更好的方法,框架方法可能只捕获 键...FilteredEditText 捕获任何输入 before 它可能出现在屏幕上 - 为了实现击键模式记录器,需要将预期的字符串拆分为 ArrayList,这也将保存各个击键之间的持续时间;一旦记录下来,就可以使用收集到的信息进行比较。

/**
 * Filtered {@link AppCompatEditText}
 * @author Martin Zeitler
 */
public class FilteredEditText extends AppCompatEditText {

    private static final String LOG_TAG = FilteredEditText.class.getSimpleName();

    private String expectedString = null;

    public FilteredEditText(Context context) {
        super(context);
    }

    public FilteredEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public FilteredEditText(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public void setExpectedString(@NonNull String value) {
        this.expectedString = value;
        this.setupInputFilter();
    }

    public void setupInputFilter() {
        this.setFilters(new InputFilter[] {
            new InputFilter() {
                public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int destStart, int destEnd) {
                    if (source.length() > 0 && source.charAt(end-1) == expectedString.charAt(destEnd)) {

                        /* valid input received */
                        Log.d(LOG_TAG, "input accepted: " + String.valueOf(source.charAt(end-1)));
                        return source;

                    } else {

                        /* invalid input received */
                        Log.d(LOG_TAG, "input rejected: " + String.valueOf(source.charAt(end-1)) + " - expected: " + String.valueOf(expectedString.charAt(destEnd)));
                        return "";
                    }
                }
            }
        });
    }

    /** hardware event  */
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        Log.d(LOG_TAG, "onKeyDown()");
        return super.onKeyDown(keyCode, event);
    }

    /** hardware event  */
    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        Log.d(LOG_TAG, "onKeyUp()");
        return super.onKeyUp(keyCode, event);
    }
}

使用示例:

FilteredEditText mTextInput = findViewById(R.id.text_input);
mTextInput.setExpectedString("9RJhl6aH0n");

Logcat 输出:

D/FilteredEditText: input accepted: 9
D/FilteredEditText: input rejected: r - expected: R
D/FilteredEditText: input rejected: 4 - expected: R
D/FilteredEditText: input accepted: R

到目前为止,我已经使用软件键盘对其进行了测试……而我目前无法使用 BT 硬件键盘对其进行测试,因为电池没电了。我假设InputFilter 捕获所有输入。

几乎没有任何OnKeyUpOnKeyDown 事件被软件键盘触发可以得到补偿,因为当知道击键何时被过滤时,这仍然会导致类似的模式——即使击键的持续时间不能由于软件键盘的限制,不能测量击键的攻击速度 - 唯一可能的解决方法是强制使用硬件键盘或创建一个为所有键发出这些事件的软件键盘(与默认的GBoard相反,也不是SwiftKey)。我现在只是想知道滑动打字和语音打字......因为这是物理击键动态几乎没有考虑的东西。甚至给GBoard 留下了反馈,因为在某些情况下选择性地发出键码会很有帮助。

documentation 也明确说明:

当使用KeyEvent 类和相关 API 处理键盘事件时,您应该期望此类键盘事件仅来自硬件键盘。您永远不应依赖接收软输入法(屏幕键盘)上任何键的键事件。

人们仍然可以使用硬件事件,同时拥有发出它们的按钮;例如:

/**
 * Fake Hardware {@link AppCompatButton}
 * @see <a href="https://developer.android.com/reference/android/view/KeyEvent">KeyEvent</a>
 * @author Martin Zeitler
 */
public class FakeHardwareButton extends AppCompatButton {

    private BaseInputConnection  mInputConnection;

    private int keyCode = KeyEvent.KEYCODE_9;
    private KeyEvent keyDown;
    private KeyEvent keyUp;

    public FakeHardwareButton(Context context) {
        this(context, null);
    }

    public FakeHardwareButton(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public FakeHardwareButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @SuppressLint("ClickableViewAccessibility")
    private void setupInputConnection(View targetView) {

       this.mInputConnection = new BaseInputConnection(targetView, true);
       this.keyDown = new KeyEvent(KeyEvent.ACTION_DOWN, this.keyCode);
       this.keyUp = new KeyEvent(KeyEvent.ACTION_UP, this.keyCode);

       this.setOnTouchListener(new View.OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch(event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        mInputConnection.sendKeyEvent(keyDown);
                        return true;

                    case MotionEvent.ACTION_UP:
                        mInputConnection.sendKeyEvent(keyUp);
                        return true;
                }
                return false;
            }
        });
    }
}

问题只是,例如。 KeyEvent.KEYCODE_9KeyEvent.KEYCODE_NUMPAD_9 是不一样的,因此在数字键的情况下总是必须比较 String 表示。

【讨论】:

    猜你喜欢
    • 2021-12-23
    • 2014-02-02
    • 1970-01-01
    • 1970-01-01
    • 2018-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多