Peripheral input devices, such as: Bluetooth keyboard, USB keyboard, barcode scanner ...
As usually in the development of pure software programs, bloggers in the demand for Android devices and peripherals to interact with a bit overwhelmed. My initial thinking is this: since it is a Bluetooth connection, that is not the socket, then intercept his I/O stream and then parse the content inside ... Isn't that OK?
However, things are not so simple, first parsing the data flow is a difficult point, and in case my Bluetooth connection to a USB connection, or WiFi, then you have to change it?
Referring to the online program found that peripherals are through the KeyEvent event mechanism of Android interaction, since it is so I can no longer care about the way the peripheral is connected, directly intercept the incident sent by the peripheral, and can also directly get to the input content!
This article will go through an Android device and the scanner connection case to tell you about the Android event mechanism first of all I use a specific class library
Here is the class library of the Bluetooth scanner I wrote, uploaded to GitHub
Https://github.com/sally519/BarCode-android
Let's go straight to see how it's used.
public class Mainactivity extends Appcompatactivity implements Barcodeipml.onscansuccesslistener {// Activity implements the Barcodeipml.onscansuccesslistener pretext that the callback succeeds when the pretext private barcodeipml BARCODEIPML = new BARCODEIPML ();p rivate TextView textview;private TextView mtv;private static final String tag= "mainactivity"; @Overrideprotected void OnCreate ( Bundle savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview (R.layout.activity_main); Set sweep code successful callback listener Barcodeipml.setongunkeypresslistener (this); MTv = (TextView) Findviewbyid (R.ID.MTV);} Method of overriding event distribution @overridepublic Boolean dispatchkeyevent (KeyEvent event) {if (Barcodeipml.iseventfrombarcode (event)) { Barcodeipml.analysiskeyevent (event); return true; } log.e ("KeyCode", Event.getkeycode () + ""); Return Super.dispatchkeyevent (event);} @overrideprotected void Onresume () {super.onresume () when the activity receives focus; try {barcodeipml.hasconnectbarcode (); } catch (Devicepairednotfoundexception e) { E.printstacktrace (); LOG.E (TAG, "Badcode gun is not connected! "); }}//The implementation of the pretext, the callback after the successful sweep code, write your own implementation @overridepublic void Onscansuccess (String barcode) {LOG.E ("Mcallback", barcode); Mtv.settext (barcode);} Binds to the activity life cycle to prevent memory leaks @overrideprotected void OnDestroy () {Super.ondestroy (); Barcodeipml.oncomplete ();}}
From the names of comments and methods we can probably determine the function of each method, and let's look at one of the most critical methods
Dispatchkeyevent (KeyEvent event)
You first need to know that this method returns a Boolean
@Overridepublic boolean dispatchKeyEvent(KeyEvent event) { if (barCodeIpml.isEventFromBarCode(event)) { barCodeIpml.analysisKeyEvent(event); return true; } Log.e("keycode",event.getKeyCode()+""); return super.dispatchKeyEvent(event);}
When I return to a true, this event will be consumed by us (the main operation in the class library is to get keycode, that is, the contents of the peripheral device input), will not be handed over to the system processing. In the above code I get this event after I call the class library method to determine whether he is from the peripheral devices, if so we will intercept their own processing, no longer to the system, otherwise we leave the system processing. This method should be familiar to everyone, we often use to rewrite the back key or home button.
Then we go in dispatchkeyevent inside to see, the system is how to deal with this event, directly in the activity to view the source code
/** * Called to process key events. You can override this to intercept all * key events before they is dispatched to the window. Be sure to call * This implementation for key events, should be handled normally. * * @param event the key event. * * @return Boolean return True if this event is consumed. */public boolean dispatchkeyevent (KeyEvent event) {onuserinteraction (); Let action bars open menus on response to the menu key prioritized over//the window handling it final int Keyco de = Event.getkeycode (); if (keycode = = Keyevent.keycode_menu && Mactionbar! = null && mactionbar.onmenukeyevent (event)) {return true; } else if (event.isctrlpressed () && Event.getunicodechar (Event.getmetastate () & ~keyevent.meta_ctrl _mask) = = ' < ') {//Capture the control-< and send focus to the ActionBar final int action = Event.get Action (); if (action = = keyevent.action_down) {finAl ActionBar ActionBar = Getactionbar (); if (ActionBar! = null && actionbar.isshowing () && Actionbar.requestfocus ()) {Meatkeyupeven T = true; return true; }} else if (action = = keyevent.action_up && meatkeyupevent) {meatkeyupevent = false; return true; } }
The
Source code is not complicated, the comment says you can intercept the event before the event is sent to the window, but to execute on the key event, the key event here may be the back key or the home key.
Let's take a step-by-step analysis, let's look at Onuserinteraction ()
/** * Called whenever a key, touch, or Trackball event is dispatched to the activity. Implement This method if you wish to know that the user have * interacted with the device in some a while your activity I S running. * This callback and {@link #onUserLeaveHint} is intended to help * activities Manage status bar notifications Intelligent Ly Specifically, * for helping activities determine the proper time to cancel a notfication. * * <p>all calls to your activity ' s {@link #onUserLeaveHint} callback'll * be accompanied by calls to {@link #onUs Erinteraction}. This * ensures that your activity would be told of relevant user activity such * as pulling down the notification pane and Touching an item there. * * <p>note that this callback would be invoked for the touch "action * that begins a touch gesture Be invoked for the touch-moved * and touch-up actions, that follow. * * @see #onUserLeaveHint () */public void Onuserinteraction () {}
The implementation is actually empty, and the note says that when the event is distributed to the activity, you can implement this method to know whether the user is interacting with the current activity. Onuserinteraction () and Onuserleavehint () are intended to help the activity better manage push messages, which will be called with the former, which also says Onuserinteraction () may not be invoked with the movement of the finger.
As a result, we also know that onuserinteraction () is called at the beginning of the event distribution, and we can use this and the method to listen to the user's interaction with the activity.
Let's keep looking down.
// Let action bars open menus in response to the menu key prioritized over// the window handling itfinal int keyCode = event.getKeyCode();if (keyCode == KeyEvent.KEYCODE_MENU && mActionBar != null && mActionBar.onMenuKeyEvent(event)) { return true;}
First get the user's input content keycode, after the intention is obvious, if the user clicked on a toolbar or Actionbar menu that directly return a true, we just said return a true meaning that the event is no longer given to the system processing, Return a false will still need to hand over to the system, the purpose of this is to throw our events to toolbar or Actionbar to deal with.
Then look down.
else if (event.isCtrlPressed() && event.getUnicodeChar(event.getMetaState() & ~KeyEvent.META_CTRL_MASK) == ‘<‘) { // Capture the Control-< and send focus to the ActionBar final int action = event.getAction(); if (action == KeyEvent.ACTION_DOWN) { final ActionBar actionBar = getActionBar(); if (actionBar != null && actionBar.isShowing() && actionBar.requestFocus()) { mEatKeyUpEvent = true; return true; } } else if (action == KeyEvent.ACTION_UP && mEatKeyUpEvent) { mEatKeyUpEvent = false; return true; }
First judging condition event.isctrlpressed () &&event.getunicodechar (Event.getmetastate () & ~keyevent.meta_ctrl_mask) = = ' < ' may be a bit abstract, but the following note tells us that the intent of this code is to capture the "<" key, then determine whether Actionbar is in the request focus, if it is forced to action_up events (that is, press the screen to lift up that) consumption, no longer handled by the system, and forcibly let Actionbar get the focus, to actionbar treatment. Otherwise told ACTIVITYACTION_UP the incident has not been consumed.
Understand the above content we can arbitrarily intercept events, and through KeyCode know whether to click on the virtual keyboard, the specific click on which key? If it is a return, it sends its contents through a callback to the activity, thereby obtaining the contents of the peripheral input device. You can see the details of usage in https://github.com/sally519/BarCode-android.
#小结
Well, let's summarize a few points that need special attention.
- Dispatchkeyevent (KeyEvent event), but we return true, the event will be consumed, will not be processed in the system, and when it returns false, it is also referred to the system for processing
- Onuserinteraction () and Onuserleavehint () can be used to listen to the user's interaction with the activity, note that the activity must be the focus
- We need to pay attention to the home button back key and other common keys, if there is no special needs, remember to throw them to the system processing
Bloggers inevitably have negligence and omission, if there are errors or doubts welcome correction! The above content are original, welcome to pay attention to Bo Master!
Skillfully use the event distribution mechanism to hold the Android peripherals with me