安卓键盘输入识别

一、     文档概述

本文档主要描述如何对安卓系统中外部键盘输入进行识别,根据输入设备的不同采取不同的操作。

二、     原理说明

系统使用的是CubieBoard2开发板(即树莓派3),运行安卓4.2操作系统。其硬件的结构如下:








按照门禁系统的业务流程,正常情况下通过物理按键输入房号进行呼叫或者开门密码,同时也可以通过刷ID或IC卡直接开门。

在使用LINUX或其他较为底层的嵌入式系统中,根据接口的不同,可以轻易的识别外部输入设备,从而进行业务判断。而本应用场景基于安卓系统,由于良好的封装性,底层输入对于上层应用来说,都是键盘输入,并没有明显的区分输入究竟是物理按键还是RFID读卡器。

不过,在对于安卓系统的一定了解之后,发现底层输入最终通过事件发送给安卓系统,安卓系统对获取到的事件进行处理。然后发现EditText中有这样的一个接口:

public boolean onKey(View v, int keyCode, KeyEvent event);

于是,这里猜想,根据KeyEvent的信息应该可以识别不同的输入设备。

于是重写该接口,将每次获取到的事件都打印出来:

editText = (EditText) findViewById(R.id.et_main_num);
editText.setOnKeyListener(new OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
	Log.v("KEYEVENT",event.getDevice().toString());
	return false;//返回false表示事件能够被后续的服务所获取;返回true表示该按键输入事件不再分发给后续服务。
	}
});

然后分别进行按键输入和RFID刷卡输入,可看到如下信息:

物理按键输入:
V/KeyEvent(8551): Input Device 8: RFID Reader With Keyboard USB RFID Reader
V/KeyEvent(8551):   Descriptor: b7e9cbd07a552feaf97d1ae331d71a89ea1007c9
V/KeyEvent(8551):   Generation: 28
V/KeyEvent(8551):   Location: external
V/KeyEvent(8551):   Keyboard Type: alphabetic
V/KeyEvent(8551):   Has Vibrator: false
V/KeyEvent(8551):   Sources: 0x101 ( keyboard )
RFID刷卡输入:
V/KeyEvent(8551): Input Device 6: sw-keyboard
V/KeyEvent(8551):   Descriptor: 485d69228e24f5e46da1598745890b214130dbc4
V/KeyEvent(8551):   Generation: 10
V/KeyEvent(8551):   Location: built-in
V/KeyEvent(8551):   Keyboard Type: non-alphabetic
V/KeyEvent(8551):   Has Vibrator: false
V/KeyEvent(8551):   Sources: 0x101 ( keyboard )

可以看出,KeyEvent中的信息包含了设备的名称,描述符等信息,在处理时可以根据这些信息区分输入设备。其中Sources字段表明无论哪种输入,均被安卓系统识别为键盘输入。

通过这个实验,发现每次按键输入或者刷卡输入时,KeyEvent都会被打印两次,导致这个的原因是因为onKey()会分别在ACTION_DOWN和ACTION_UP时被触发,ACTION_DOWN和ACTION_UP分别对应按键按下和按键松开动作。

这里需要注意的是,在动作为ACTION_UP的KeyEvent事件之后,按键的值才会显示在对应的EditText上。如果在动作为ACTION_DOWN的KeyEvent事件中,获取EditText的文本,只能获取到不包括当前按下的按键的文本,当前的按键值可以通过keyCode获取。

利用这个特性,当不需要将按键值显示到EditText上时,可以只处理ACTION_DOWN的事件,丢弃ACTION_UP的事件。

    可参照如下代码:

cardID=new StringBuffer();
editText = (EditText) findViewById(R.id.et_main_num);
editText.setOnKeyListener(new OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
String editString = ((EditText) v).getText().toString();
//根据输入设备的不同,进行不同的处理,分为ADC键盘、RFID读卡器和其他设备(如鼠标等)
if(event.getDevice().getName().contains("RFID")){//RFID输入主要读取IC卡的ID
editText.setText("");
if(event.getAction()==KeyEvent.ACTION_DOWN){
		int tmpKeyCode=event.getKeyCode();
		if(tmpKeyCode==KeyEvent.KEYCODE_ENTER){//获取到ENTER字符时,表示ID卡已读取完成。							
Log.v("KEYEVENT","Card ID:"+cardID);
			cardID.setLength(0);							
}else{
//将获取到的KEYCODE添加到字符串,keycode2Char为自定义函数,将KEYCODE转换为char
cardID.append(keycode2Char(tmpKeyCode));
		}
		//直接返回true,后续的系统监听将得不到这个事件,这里将获取到的数字不在EditText上显示。
		return true;
	}else if(event.getAction()==KeyEvent.ACTION_UP){
		//不处理ACTION_UP事件
		return true;
	}					
}else if (event.getDevice().getSources()==257){//257为键盘输入,ADC键盘或者其他键盘输入
//为了使特定的字符不显示在editText上,在收到ACTION_DOWN事件后进行按键处理,
	if(event.getAction()==KeyEvent.ACTION_DOWN){	
		…//按键处理
		return true;
	}else if(event.getAction()==KeyEvent.ACTION_UP){
		//不处理ACTION_UP事件
		return true;
	}						
}
	//除了以上的几种设备之外,其他的设备返回false,避免其他设备无法正常工作
	return false;
}
});

需要注意的是,这里的onKey()接口只会在物理输入时进行触发,包括外接的鼠标键盘。而使用系统自带的虚拟键盘输入时并不会触发。




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值