Android USB掃碼器/門禁/外接鍵盤等區(qū)分識別

簡介:市面上很多外接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ù)字無效注釋

? ? }

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載匆背,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者呼伸。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市钝尸,隨后出現(xiàn)的幾起案子括享,更是在濱河造成了極大的恐慌,老刑警劉巖蝶怔,帶你破解...
    沈念sama閱讀 211,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件奶浦,死亡現(xiàn)場離奇詭異兄墅,居然都是意外死亡踢星,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評論 3 385
  • 文/潘曉璐 我一進(jìn)店門隙咸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來沐悦,“玉大人,你說我怎么就攤上這事五督〔胤瘢” “怎么了?”我有些...
    開封第一講書人閱讀 157,435評論 0 348
  • 文/不壞的土叔 我叫張陵充包,是天一觀的道長副签。 經(jīng)常有香客問我,道長基矮,這世上最難降的妖魔是什么淆储? 我笑而不...
    開封第一講書人閱讀 56,509評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮家浇,結(jié)果婚禮上本砰,老公的妹妹穿的比我還像新娘。我一直安慰自己钢悲,他們只是感情好点额,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,611評論 6 386
  • 文/花漫 我一把揭開白布舔株。 她就那樣靜靜地躺著,像睡著了一般还棱。 火紅的嫁衣襯著肌膚如雪载慈。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,837評論 1 290
  • 那天珍手,我揣著相機(jī)與錄音娃肿,去河邊找鬼。 笑死珠十,一個胖子當(dāng)著我的面吹牛料扰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播焙蹭,決...
    沈念sama閱讀 38,987評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼晒杈,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了孔厉?” 一聲冷哼從身側(cè)響起拯钻,我...
    開封第一講書人閱讀 37,730評論 0 267
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎撰豺,沒想到半個月后粪般,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,194評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡污桦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,525評論 2 327
  • 正文 我和宋清朗相戀三年亩歹,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凡橱。...
    茶點(diǎn)故事閱讀 38,664評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡小作,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出稼钩,到底是詐尸還是另有隱情顾稀,我是刑警寧澤,帶...
    沈念sama閱讀 34,334評論 4 330
  • 正文 年R本政府宣布坝撑,位于F島的核電站静秆,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏巡李。R本人自食惡果不足惜抚笔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,944評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望击儡。 院中可真熱鬧塔沃,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,764評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至鸽疾,卻和暖如春吊洼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背制肮。 一陣腳步聲響...
    開封第一講書人閱讀 31,997評論 1 266
  • 我被黑心中介騙來泰國打工冒窍, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人豺鼻。 一個月前我還...
    沈念sama閱讀 46,389評論 2 360
  • 正文 我出身青樓综液,卻偏偏與公主長得像,于是被迫代替她去往敵國和親儒飒。 傳聞我的和親對象是個殘疾皇子谬莹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,554評論 2 349

推薦閱讀更多精彩內(nèi)容