我有个问题。
我在Android设备上进行Keystroke dynamics应用。
现在,我就与措施字符串和EditText
的活动。我想赶上软键盘的KeyDown
和KeyUp
事件。
我的问题是,什么是捕捉KeyUp
和KeyDown
在Android与Java的最佳方式?如果EditText
是一个好的选择吗?如果有方法来捕捉任何按键?
编辑
我想检测从字符串键上方和衡量按下它的时候,(在KeyDown
启动措施,停止对KeyUp
为例)。如果可能的话,我想阻止未在我test string
提到的其他键(其9RJhl6aH0n
,就像在我的屏幕)
Aaditi
我实现到目前为止是这样的,但在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;
}
});
OnKeyUp
&OnKeyDown
事件将不会削减它,因为软键盘几乎没有发出任何的这些。
这里有一个粗略的原型,它过滤根据期望的字符串的字符输入。有很多改进的余地;而自定义实现仍然比试图使用框架方法,这可能只是抓住关键⌫一个更好的方法...的FilteredEditText
捕获任何输入之前,它可能会出现在屏幕上 - 为了实现一个按键模式记录,期望的字符串将需要被分成一个ArrayList
,这也将保持在各个键击之间的持续时间;一旦记录可以使用收集到的信息进行比较。
/**
* Filtered {@link AppCompatEditText}
* @author Martin Zeitler
* @version 1.0.0
**/
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
捕获所有输入。
这几乎没有任何OnKeyUp
和OnKeyDown
事件是由软件键盘触发可以得到补偿,因为不知何时被过滤击键时,这仍然会导致类似模式 - 即使击键的持续时间无法测量,也没有攻击速度击键,由于软键盘的限制 - 唯一可能的解决方法将被强制执行硬件键盘或创建一个软件键盘发出这些事件的所有键(与默认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
* @version 1.0.0
**/
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_9
和KeyEvent.KEYCODE_NUMPAD_9
是不一样的,因此,人们总是给String
表示比较数字键的情况。
你只需要使用活动的调度事件
像这样:
@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
}
});
你需要仔细覆盖以下功能:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_A:
{
//your Action code
return true;
}
}
return super.onKeyDown(keyCode, event);
}
并为EditText上:
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)
{
}
);
您可以使用dispatchKeyEvent(KeyEvent event)
在Activity
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
Log.i("key pressed", String.valueOf(event.getKeyCode()));
return super.dispatchKeyEvent(event);
}
为了检测按下的键