Android设备标准HID协议(外接输入设备)接入蓝牙扫描枪的各种坑与解决办法

因工作需要最近在做一款蓝牙条码、二维码扫描器枪支持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()方法导致界面退出了。


你可能感兴趣的:(Bluetooth,开发了解)