因工作需要最近在做一款蓝牙条码、二维码扫描器枪支持Android设备(执行标准HID协议)的外接输入设备,在开发过程中遇到一些问题,在此记录下来,以便供大家借鉴学习,希望有类似需求的同行少走些弯路。好了,废话不多说步入正题:
我们的需求大致是这样的:
调用系统设置蓝牙进行蓝牙连接,连接成功后获取蓝牙扫描枪的数据内容,最后将得到的数据做下一步的逻辑处理。
网上我找了很多的资料,也发现了前人造的很多的轮子,其中最主要有一篇是很值得借鉴与学习的,我将地址放置在下面,大家也可以参考借鉴一下:
Android设备获取扫码枪扫描内容-一座小楼的专栏
其中详细描述了android设备与蓝牙扫描枪配对链接、状态获取、权限添加以及数据内容的扫描获取等处理。
与他有一点不同的是我需要在碎片(Fragment)上去处理dispatchKeyEvent(KeyEvent event
)事件,至于怎么去调用下面告诉大家一个方法。
1.在Fragment中调用Activity的回调方法dispatchKeyEvent(KeyEvent event)
对于此,网上同样也是介绍了一大堆,我才用的方法是:
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if(event.getKeyCode() == KeyEvent.KEYCODE_BACK
&& event.getAction() == KeyEvent.ACTION_DOWN){
return super.dispatchKeyEvent(event);
}else{
if (mDispatchKeyEvent != null) {
mDispatchKeyEvent.dispatchKeyEvent(event);
}
return true;
}
}
public interface DispatchKeyEvent{
public void dispatchKeyEvent(KeyEvent event);
}
public void setOnDispatchKeyEvent(DispatchKeyEvent mDispatchKeyEvent){
this.mDispatchKeyEvent = mDispatchKeyEvent;
}
在Activity重写
dispatchKeyEvent(KeyEvent event)方法,并向外提供接口
DispatchKeyEvent
让Fragment实现接口,同时回调自定义的方法
public void dispatchKeyEvent(KeyEvent event);
即可解决Fragment调用dispatchKeyEvent方法的问题了。
2.扫描枪获取到内容以后,程序无故退出。
程序调试过程中,出现:
09-21 09:24:03.377: W/Binder(1005): Caught a RuntimeException from the binder stub implementation.
09-21 09:24:03.377: W/Binder(1005): java.lang.NullPointerException
09-21 09:24:03.377: W/Binder(1005): at android.inputmethodservice.IInputMethodWrapper.setSessionEnabled(IInputMethodWrapper.java:280)
09-21 09:24:03.377: W/Binder(1005): at com.android.internal.view.IInputMethod$Stub.onTransact(IInputMethod.java:129)
09-21 09:24:03.377: W/Binder(1005): at android.os.Binder.execTransact(Binder.java:404)
09-21 09:24:03.377: W/Binder(1005): at dalvik.system.NativeStart.run(Native Method)
09-21 09:24:03.377: W/InputMethodManagerService(823): Got RemoteException sending setActive(false) notification to pid 16942 uid 1000
警告异常,查找相关资料,大家无非是以下几种办法:
在清单文件相应的Activity目录下添加
android:configChanges="keyboard|keyboardHidden|orientation|navigation|screenSize"
Activity中重写
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
方法等。
我按照以上方法操作,结果均未解决我的程序出现的问题,至此,我怀疑是不是有其他的自己没有注意到的细节导致的呢(因为在Demo中Activity页面没有Edittext的情况下,扫描枪扫描获取到数据一切都是正常的),于是我又仔细看了一边代码,并且查看了一下外接键盘调用所触发方法的执行顺序:
当键盘按下(不松开)时的触发顺序 -> dispatchKeyEvent –> onUserInteraction –> onKeyDown
如果按下紧接着松开,则会紧跟再触发–> dispatchKeyEvent –> onUserInteraction–>onKeyUp
由此看来每次点击松开的过程中dispatchKeyEvent是触发两次。dispatchKeyEvent是做按键处理和分发的工作
明白了以上原理方法执行的顺序之后,我去查找,原来我最初的写法是
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (mDispatchKeyEvent != null) {
mDispatchKeyEvent.dispatchKeyEvent(event);
}
return super.dispatchKeyEvent(event);
}
public interface DispatchKeyEvent{
public boolean dispatchKeyEvent(KeyEvent event);
}
public DispatchKeyEvent mDispatchKeyEvent;
public void setOnDispatchKeyEvent(DispatchKeyEvent mDispatchKeyEvent){
this.mDispatchKeyEvent = mDispatchKeyEvent;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
finish();
}
return super.onKeyDown(keyCode, event);
}
这就豁然开朗了,是自己在
dispatchKeyEvent方法中执行回调方法时并没有自己处理事件,系统默认返回
return super.dispatchKeyEvent(event);使得界面相应onKeyDown()方法导致界面退出了。