外围输入设备,例如:蓝牙键盘,usb键盘,条形码扫码枪…
由于平时都是在做纯软件程序的开发,博主在需求遇到android设备与外围设备交互时有点不知所措。我最初的思路是这样:既然是蓝牙连接,那不就是套接字吗,那么截获他的I/O流然后解析里面的内容……那不就好啦?
然而事情并没有那么简单,首先解析数据流是一个难点,再一个万一我蓝牙连接换成usb连接,或者wifi,那不就得再改了?
参考了网上的方案后发现,外围设备是通过KeyEvent事件机制android交互的,既然是这样那我就不用再关心外设是通过什么方式连接的,直接截获外设发送的事件,并且还可直接获取到输入内容!
本文将通过一个android设备与扫码枪连接案例来向大家详述android的事件机制
以下就是我写的的蓝牙扫码枪的类库,已上传至github https://github.com/sally519/BarCode-android
我们直接来看看是怎么用的
<代码>公共类MainActivity AppCompatActivity实现BarCodeIpml延伸。OnScanSuccessListener {//活动实现了BarCodeIpml.OnScanSuccessListener借口,即回调成功时的借口 私人BarCodeIpml BarCodeIpml=new BarCodeIpml (); 私人TextView TextView; 私人TextView mTv; 私有静态最终字符串标签=癕ainActivity”; @Override 保护无效onCreate(包savedInstanceState) { super.onCreate (savedInstanceState); setContentView (R.layout.activity_main);//设置扫码成功的回调监听 barCodeIpml.setOnGunKeyPressListener(这个); mTv=(TextView) findViewById (R.id.mTv); }//重写事件分发的方法 @Override 公共布尔dispatchKeyEvent (KeyEvent事件){ 如果(barCodeIpml.isEventFromBarCode(事件)){ barCodeIpml.analysisKeyEvent(事件); 返回true; } Log.e(“键码”,event.getKeyCode () + " "); 返回super.dispatchKeyEvent(事件); }//在活动获得焦点时 @Override 保护无效onResume () { super.onResume (); 尝试{ barCodeIpml.hasConnectBarcode (); }捕捉(DevicePairedNotFoundException e) { e.printStackTrace (); 日志。e(标签,“badcode枪未连接!”); } }//借口的实现,扫码成功后的回调,写你自己的实现 @Override 公共空间onScanSuccess(字符串条形码){ 日志。e (“mcallback”,条形码); mTv.setText(条形码); }//与活动生命周期绑定,防止内存泄漏 @Override 保护无效onDestroy () { super.onDestroy (); barCodeIpml.onComplete (); } }代码>
从注释和方法的名称我们大概可以判断出各个方法的作用,我们来看其中最关键的一个方法
大家首先需要知道,这个方法返回一个布尔值
<代码> @Override 公共布尔dispatchKeyEvent (KeyEvent事件){ 如果(barCodeIpml.isEventFromBarCode(事件)){ barCodeIpml.analysisKeyEvent(事件); 返回true; } Log.e(“键码”,event.getKeyCode () + " "); 返回super.dispatchKeyEvent(事件); }代码>
当我返回一个真正的时候,这个事件就会被我们消费(类库里的主要操作就是获取键码,即外围设备输入的内容),不会再交给系统处理。在以上的代码中我拿到这个事件后我调用类库的方法判断他是否来自外围设备,如果是的话我们自己将其截获处理,不再交给系统,否则的话我们交由系统处理。这个方法大家应该比较熟悉,我们常常用来重写回键或者回家键。
之后我们进去dispatchKeyEvent里面看一下,系统是如何处理这个事件的,直接在活动中查看源码
<代码>/* * *处理关键事件。你可以覆盖这个拦截 *关键事件之前派往窗外。一定要联系 *这个实现的关键事件处理正常。 * * @param事件的关键事件。 * * @return布尔返回true,如果这个事件被消耗。 */公共布尔dispatchKeyEvent (KeyEvent事件){ onUserInteraction ();//让行动酒吧开放菜单的菜单主要优先//窗口处理 最后一个int键码=event.getKeyCode (); 如果(键码==KeyEvent。KEYCODE_MENU,, mActionBar !=零,,mActionBar.onMenuKeyEvent(事件)){ 返回true; }else if (event.isCtrlPressed (),, event.getUnicodeChar (event.getMetaState (),~ KeyEvent.META_CTRL_MASK)==& lt;) {//捕获控制& lt;和发送ActionBar焦点 最后一个int action=event.getAction (); 如果(action==KeyEvent.ACTION_DOWN) { 最后ActionBar ActionBar=getActionBar (); 如果(actionBar !=零,,actionBar.isShowing (),,actionBar.requestFocus ()) { mEatKeyUpEvent=true; 返回true; } 如果(action==KeyEvent}其他。ACTION_UP,,mEatKeyUpEvent) { mEatKeyUpEvent=false; 返回true; } }巧用事件分发机制,和我一起保持住android外围设备