簡介:市面上很多外接USB錄入設(shè)備為了節(jié)約成本占锯,都是模擬Android鍵盤按下彈起今艺,這樣就不需要開發(fā)jar而且跨平臺。
先寫個工具類 僻孝,將每次模擬鍵盤內(nèi)容拼接导帝,因?yàn)槲覍?shí)際開發(fā)不會出現(xiàn)多設(shè)備同時工作,所以沒有區(qū)分設(shè)備穿铆,如果有多設(shè)備同時錄入您单,把StringBuilder換成Map<Integer,StringBuilder>就可以了,Key是錄入設(shè)備的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();
? ? }
/**
* 掃碼設(shè)備事件解析
*/
? ? 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);
? ? ? ? ? ? }
//如果是回車睹限,掃碼/門禁/鍵盤認(rèn)為錄入結(jié)束
? ? ? ? ? ? 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轉(zhuǎn)為char
*
? ? * @param caps? ? 是不是大寫
? ? * @param keyCode 按鍵
? ? * @return 按鍵對應(yīng)的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);
? ? ? ? }
}
/**
* 按鍵對應(yīng)的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設(shè)備的地址或ProductId,如果公司設(shè)備的ProductId固定那就沒必要用地址判斷讯檐,我們需求是設(shè)備不一定是同一家公司羡疗,ProductId也肯定不一樣,所以只能動態(tài)配置每個設(shè)備的地址别洪,最后通過配置的地址和USB遍歷的地址拿出ProductId叨恨,最后跟錄入設(shè)備對比就知道是哪臺設(shè)備了。
????????一開始不知道設(shè)備鏈接地址挖垛,就重寫第三步痒钝,自己挨個試一遍秉颗,拿出ProductId再根據(jù)第一步ProductId對比拿出USB的?DeviceName也就是USB地址(設(shè)備固定就跳過這一步)。
1.識別USB設(shè)備:根據(jù)配置的地址對比拿到ProductId(外接設(shè)備的產(chǎn)品ID)
private int usbCardId, usbScanId;
/**
* 獲取所有usb設(shè)備
*/
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.創(chuàng)建工具類:根據(jù)ProductId做對應(yīng)的事情
//攔截掃碼器回調(diào),獲取掃碼內(nèi)容
scanKeyManager =new ScanKeyManager((value, type) -> {
if (type ==usbCardId) {
//門禁結(jié)果
getUser(value);
? ? }else if (type ==usbScanId) {
//掃碼器結(jié)果
getScanResult(value);
? ? }else {
if (userInfo ==null) {
//其他操作
}
});
3.重寫:如果遇到安卓虛擬鍵盤錄入數(shù)字無效,就將下邊注釋部分放開晌块,經(jīng)測試我這臺設(shè)備自身虛擬鍵盤錄入不會走dispatchKeyEvent這個方法爱沟,其它安卓系統(tǒng)可能會走而且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;//虛擬鍵盤錄入數(shù)字無效放開
? ? ? ? }
//? ? ? ? return super.dispatchKeyEvent(event);//虛擬鍵盤錄入數(shù)字無效放開
? ? ? ? return true;//虛擬鍵盤錄入數(shù)字無效注釋
? ? }