The Android device acquires the scanning content of the code scanning gun

  • 2021-12-21 05:01:49
  • OfStack

Bar code scanning gun can be seen everywhere now, which can scan the bar code content quickly, which is faster than any mobile phone camera scanning code, not 1:00 or 2:00.
In order to save costs, the code scanning gun can be directly connected to android or other devices through Bluetooth.

So how does android device get scanned content through Bluetooth?

1. Bluetooth pairing, connecting devices

Open the system settings, find Bluetooth, open the code scanning gun, and pair the code scanning gun equipment. Enter a fixed pairing code, which is written in the instruction manual of a code scanning gun. After the pairing is completed, the display device is connected. Just ok.

2. Configure permissions in 2. AndroidManifest

Add Bluetooth permissions to the AndroidManifest. xml file in the android project.


<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

3. Detect the connection status of the code scanning gun

Generally speaking, the code scanning gun equipment is also equivalent to the common external input equipment type and external keyboard.

My code scanning gun device returns the following Bluetooth type.

BluetoothClass.Device.Major.PERIPHERAL

Generally speaking, the information of our code scanning gun equipment can be obtained in the following way.


Set<BluetoothDevice> blueDevices = mBluetoothAdapter.getBondedDevices();

if (blueDevices == null || blueDevices.size() <= 0) {
    return false;
}

for (Iterator<BluetoothDevice> iterator = blueDevices.iterator(); iterator.hasNext(); ) {
    BluetoothDevice bluetoothDevice = iterator.next();

    if (bluetoothDevice.getBluetoothClass().getMajorDeviceClass() == BluetoothClass.Device.Major.PERIPHERAL) {
        //TODO  Acquiring code scanning gun equipment information 
    }

}

In the development process, it is necessary to judge whether the equipment is connected normally in real time.

mBluetoothAdapter.getBondedDevices()

This method can only determine whether the device is paired and bound. But binding does not represent a connection, so you can only give up.

public List getConnectedDevices (int profile)
public int getConnectionState (BluetoothDevice device, int profile)

Then I tried these two methods, which are available, but the device sdk must be required > 18, that is, android version 4.3 or above.

Later, I turned to think that since the code scanning gun is also an input device, we can start with the status detection of different Bluetooth devices and start with the detection of input devices instead. So,


private void hasScanGun() {
    Configuration cfg = getResources().getConfiguration();
    return cfg.keyboard != Configuration.KEYBOARD_NOKEYS;
}

Done.

4. Get the scanning content of the code scanning gun

Scanning gun, since it is an external input device, it is natural for us to start with KeyEvent.

Event resolution class


/**
 *  Code scanning gun event parsing class 
 */
public class ScanGunKeyEventHelper {

    // Delay 500ms And judging whether the code scanning is completed. 
    private final static long MESSAGE_DELAY = 500;
    // Scan code content 
    private StringBuffer mStringBufferResult = new StringBuffer();
    // Case sensitivity 
    private boolean mCaps;
    private OnScanSuccessListener mOnScanSuccessListener;
    private Handler mHandler = new Handler();

    private final Runnable mScanningFishedRunnable = new Runnable() {
        @Override
        public void run() {
            performScanSuccess();
        }
    };

    // Return scan results 
    private void performScanSuccess() {
        String barcode = mStringBufferResult.toString();
        if (mOnScanSuccessListener != null)
            mOnScanSuccessListener.onScanSuccess(barcode);
        mStringBufferResult.setLength(0);
    }

    //key Event handling 
    public void analysisKeyEvent(KeyEvent event) {

        int keyCode = event.getKeyCode();

        // Letter case judgment 
        checkLetterStatus(event);

        if (event.getAction() == KeyEvent.ACTION_DOWN) {

            char aChar = getInputCode(event);;

            if (aChar != 0) {
                mStringBufferResult.append(aChar);
            }

            if (keyCode == KeyEvent.KEYCODE_ENTER) {
                // If it is Enter key, return directly 
                mHandler.removeCallbacks(mScanningFishedRunnable);
                mHandler.post(mScanningFishedRunnable);
            } else {
                // Delay post If 500ms Inside, there are other events 
                mHandler.removeCallbacks(mScanningFishedRunnable);
                mHandler.postDelayed(mScanningFishedRunnable, MESSAGE_DELAY);
            }

        }
    }

    // Check shift Key 
    private void checkLetterStatus(KeyEvent event) {
        int keyCode = event.getKeyCode();
        if (keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT || keyCode == KeyEvent.KEYCODE_SHIFT_LEFT) {
            if (event.getAction() == KeyEvent.ACTION_DOWN) {
                // Press shift Key, representing uppercase 
                mCaps = true;
            } else {
                // Loosen shift Key for lowercase 
                mCaps = false;
            }
        }
    }


    // Get scanned content 
    private char getInputCode(KeyEvent event) {

        int keyCode = event.getKeyCode();

        char aChar;

        if (keyCode >= KeyEvent.KEYCODE_A && keyCode <= KeyEvent.KEYCODE_Z) {
            // Alphabet 
            aChar = (char) ((mCaps ? 'A' : 'a') + keyCode - KeyEvent.KEYCODE_A);
        } else if (keyCode >= KeyEvent.KEYCODE_0 && keyCode <= KeyEvent.KEYCODE_9) {
            // Figures 
            aChar = (char) ('0' + keyCode - KeyEvent.KEYCODE_0);
        } else {
            // Other symbols 
            switch (keyCode) {
                case KeyEvent.KEYCODE_PERIOD:
                    aChar = '.';
                    break;
                case KeyEvent.KEYCODE_MINUS:
                    aChar = mCaps ? '_' : '-';
                    break;
                case KeyEvent.KEYCODE_SLASH:
                    aChar = '/';
                    break;
                case KeyEvent.KEYCODE_BACKSLASH:
                    aChar = mCaps ? '|' : '\\';
                    break;
                default:
                    aChar = 0;
                    break;
            }
        }

        return aChar;

    }



    public interface OnScanSuccessListener {
        public void onScanSuccess(String barcode);
    }

    public void setOnBarCodeCatchListener(OnScanSuccessListener onScanSuccessListener) {
        mOnScanSuccessListener = onScanSuccessListener;
    }

    public void onDestroy() {
        mHandler.removeCallbacks(mScanningFishedRunnable);
        mOnScanSuccessListener = null;
    }

}

The dispatchKeyEvent method is overridden in Activity to intercept Key events.


 /**
     * Activity Intercept key event . Issue ScanGunKeyEventHelper
     *
     * @param event
     * @return
     */
    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {

        if (isScanGunEvent(event)) {
             mScanGunKeyEventHelper.analysisKeyEvent(event);
            return true;
        }
        return super.dispatchKeyEvent(event);
    }

    /**
     *  Display scanned content 
     * @param barcode  Bar code 
     */
    @Override
    public void onScanSuccess(String barcode) {
        //TODO  Display scanned content 
    }

For detailed codes, please refer to: https://github.com/czhzero/scangon

Note:

1. Some models can't judge the external keyboard information, such as 3 stars.


private void hasScanGun() {
    Configuration cfg = getResources().getConfiguration();
    return cfg.keyboard != Configuration.KEYBOARD_NOKEYS;
}

The return value of 3-star mobile phone cfg.keyboard is equal to Configuration.KEYBOARD_NOKEYS.

Therefore, for better compatibility, the following methods can be adopted


/**
 *  Judge whether the code scanning gun has been connected 
 * @return
 */
protected boolean hasScanGun() {

    Set<BluetoothDevice> blueDevices = mBluetoothAdapter.getBondedDevices();

    if (blueDevices == null || blueDevices.size() <= 0) {
        return false;
    }

    for (Iterator<BluetoothDevice> iterator = blueDevices.iterator(); iterator.hasNext(); ) {
        BluetoothDevice bluetoothDevice = iterator.next();

        if (bluetoothDevice.getBluetoothClass().getMajorDeviceClass() == BluetoothClass.Device.Major.PERIPHERAL) {
            return isInputDeviceUsed(bluetoothDevice.getName());
        }

    }

    return false;

}


private boolean isInputDeviceUsed(String deviceName) {

    int[] deviceIds = InputDevice.getDeviceIds();

    for (int id : deviceIds) {
        if (InputDevice.getDevice(id).getName().equals(deviceName)) {
            return true;
        }
    }

    return false;

}

Related articles: