简介:市面上很多外接USB录入设备为了节约成本,都是模拟Android键盘按下弹起,这样就不需要开发jar而且跨平台。
先写个工具类 ,将每次模拟键盘内容拼接,因为我实际开发不会出现多设备同时工作,所以没有区分设备,如果有多设备同时录入,把StringBuilder换成Map<Integer,StringBuilder>就可以了,Key是录入设备的ProductId,也就是代码中 mListener.onScanValue(mResult.toString(), event.getDevice().getProductId());
public class ScanKeyManager {
private StringBuildermResult;
public OnScanValueListenermListener;
private boolean mCaps;
public interface OnScanValueListener {
void onScanValue(String value, int type);
}
public ScanKeyManager(OnScanValueListener listener) {
this.mListener = listener;
this.mResult =new StringBuilder();
}
/**
* 扫码设备事件解析
*/
public void analysisKeyEvent(KeyEvent event) {
int keyCode = event.getKeyCode();
checkLetterStatus(event);
if (event.getAction() == KeyEvent.ACTION_DOWN) {
char aChar = getInputCode(mCaps, event.getKeyCode());
if (aChar !=0) {
mResult.append(aChar);
}
//如果是回车,扫码/门禁/键盘认为录入结束
if (keyCode == KeyEvent.KEYCODE_ENTER) {
if (mListener !=null) {
mListener.onScanValue(mResult.toString(), event.getDevice().getProductId());
}
mResult.delete(0, mResult.length());
}
}
}
/**
* 判断大小写
*/
private void checkLetterStatus(KeyEvent event) {
int keyCode = event.getKeyCode();
if (keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT || keyCode == KeyEvent.KEYCODE_SHIFT_LEFT) {
mCaps = event.getAction() == KeyEvent.ACTION_DOWN;
}
}
/**
* 将keyCode转为char
*
* @param caps 是不是大写
* @param keyCode 按键
* @return 按键对应的char
*/
private char getInputCode(boolean caps, int keyCode) {
if (keyCode >= KeyEvent.KEYCODE_A && keyCode <= KeyEvent.KEYCODE_Z) {
return (char) ((caps ?'A' :'a') + keyCode - KeyEvent.KEYCODE_A);
}else {
return keyValue(caps, keyCode);
}
}
/**
* 按键对应的char表
*/
private char keyValue(boolean caps, int keyCode) {
switch (keyCode) {
case KeyEvent.KEYCODE_0:
return caps ?')' :'0';
case KeyEvent.KEYCODE_1:
return caps ?'!' :'1';
case KeyEvent.KEYCODE_2:
return caps ?'@' :'2';
case KeyEvent.KEYCODE_3:
return caps ?'#' :'3';
case KeyEvent.KEYCODE_4:
return caps ?'$' :'4';
case KeyEvent.KEYCODE_5:
return caps ?'%' :'5';
case KeyEvent.KEYCODE_6:
return caps ?'^' :'6';
case KeyEvent.KEYCODE_7:
return caps ?'&' :'7';
case KeyEvent.KEYCODE_8:
return caps ?'*' :'8';
case KeyEvent.KEYCODE_9:
return caps ?'(' :'9';
case KeyEvent.KEYCODE_NUMPAD_SUBTRACT:
case KeyEvent.KEYCODE_MINUS:
return '-';
case KeyEvent.KEYCODE_EQUALS:
return '=';
case KeyEvent.KEYCODE_NUMPAD_ADD:
return '+';
case KeyEvent.KEYCODE_GRAVE:
return caps ?'~' :'`';
case KeyEvent.KEYCODE_BACKSLASH:
return caps ?'|' :'\\';
case KeyEvent.KEYCODE_LEFT_BRACKET:
return caps ?'{' :'[';
case KeyEvent.KEYCODE_RIGHT_BRACKET:
return caps ?'}' :']';
case KeyEvent.KEYCODE_SEMICOLON:
return caps ?':' :';';
case KeyEvent.KEYCODE_APOSTROPHE:
return caps ?'"' :'\'';
case KeyEvent.KEYCODE_COMMA:
return caps ?'<' :',';
case KeyEvent.KEYCODE_PERIOD:
return caps ?'>' :'.';
case KeyEvent.KEYCODE_SLASH:
return caps ?'?' :'/';
default:
return 0;
}
}
}
先要找出所有USB设备的地址或ProductId,如果公司设备的ProductId固定那就没必要用地址判断,我们需求是设备不一定是同一家公司,ProductId也肯定不一样,所以只能动态配置每个设备的地址,最后通过配置的地址和USB遍历的地址拿出ProductId,最后跟录入设备对比就知道是哪台设备了。
一开始不知道设备链接地址,就重写第三步,自己挨个试一遍,拿出ProductId再根据第一步ProductId对比拿出USB的 DeviceName也就是USB地址(设备固定就跳过这一步)。
1.识别USB设备:根据配置的地址对比拿到ProductId(外接设备的产品ID)
private int usbCardId, usbScanId;
/**
* 获取所有usb设备
*/
private void getAllUsb() {
Map usbDeviceMap = ((UsbManager) getSystemService(Context.USB_SERVICE)).getDeviceList();
if (usbDeviceMap !=null && usbDeviceMap.size() >0) {
for (UsbDevice u : usbDeviceMap.values()) {
//门禁卡的usb地址
if (u.getDeviceName().equals(BaseActivity.deviceConfig.getPathIdCar())) {
usbCardId = u.getProductId();
}else if (u.getDeviceName().equals(BaseActivity.deviceConfig.getPathScan())) {
//扫码器的usb地址
usbScanId = u.getProductId();
}
Log.i("asoduao",
"usbCardId" +usbCardId
+",usbScanId:" +usbScanId
+",usbCardPath:" + BaseActivity.deviceConfig.getPathIdCar()
+",usbScanPath:" + BaseActivity.deviceConfig.getPathScan()
+",Name:" + u.getDeviceName()
+",ProductId:" + u.getProductId());
}
}
}
2.创建工具类:根据ProductId做对应的事情
//拦截扫码器回调,获取扫码内容
scanKeyManager =new ScanKeyManager((value, type) -> {
if (type ==usbCardId) {
//门禁结果
getUser(value);
}else if (type ==usbScanId) {
//扫码器结果
getScanResult(value);
}else {
if (userInfo ==null) {
//其他操作
}
});
3.重写:如果遇到安卓虚拟键盘录入数字无效,就将下边注释部分放开,经测试我这台设备自身虚拟键盘录入不会走dispatchKeyEvent这个方法,其它安卓系统可能会走而且ProductId是0或者-1。
@SuppressLint("RestrictedApi")
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
InputDevice u = event.getDevice();
Log.i("UsbDeviceTAG",
"Name:" + u.getName()
+",id:" + u.getId()
+",ProductId:" + u.getProductId()
+",Descriptor:" + u.getDescriptor()
+",ControllerNumber:" + u.getControllerNumber()
+",Sources:" + u.getSources()
+",KeyboardType:" + u.getKeyboardType());
if (event.getDeviceId() == -1)return super.dispatchKeyEvent(event);
if (event.getKeyCode() != KeyEvent.KEYCODE_BACK) {
scanKeyManager.analysisKeyEvent(event);
// return true;//虚拟键盘录入数字无效放开
}
// return super.dispatchKeyEvent(event);//虚拟键盘录入数字无效放开
return true;//虚拟键盘录入数字无效注释
}
网友评论