androidbluetoothprofilehidinput-devices

Connection to specific HID profile bluetooth device


I connect bluetooth barcode scanner to my android tablet. barcode scanner is bonded with android device as a input device - HID profile. it shows as keyboard or mouse in system bluetooth manager. i discovered that bluetooth profile input device class exist but is hidden. class and btprofile constants have @hide annotaions in android docs.

hidden class:

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.3.1_r1/android/bluetooth/BluetoothInputDevice.java

here they should be also 3 other constants

developer.android.com/reference/android/bluetooth/BluetoothProfile.html#HEADSET

just like

public static final int INPUT_DEVICE = 4;
public static final int PAN = 5;
public static final int PBAP = 6;

that constants are simple accessible by reflection. What i need to achieve, is list of devices by hid profile(INPUT_DEVICE). it should be simple with small changes using method:

developer.android.com/reference/android/bluetooth/BluetoothA2dp.html#getConnectedDevices()

not for A2dp profile, but for hid profile accessed also by reflection methods. sadly

Class c = Class.forName("android.bluetooth.BluetoothInputDevice")

won't work.. any ideas how i should approach to the problem ? i need only list of hid devices


Solution

  • I figured out how to solve my problem. That was very helpful. First of all I needed to prepare reflection method which return input_device hidden constants of hid profile:

    public static int getInputDeviceHiddenConstant() {
        Class<BluetoothProfile> clazz = BluetoothProfile.class;
        for (Field f : clazz.getFields()) {
            int mod = f.getModifiers();
            if (Modifier.isStatic(mod) && Modifier.isPublic(mod) && Modifier.isFinal(mod)) {
                try {
                    if (f.getName().equals("INPUT_DEVICE")) {
                        return f.getInt(null);
                    }
                } catch (Exception e) {
                    Log.e(LOG_TAG, e.toString(), e);
                }
            }
        }
        return -1;
    }
    

    Instead of that function, I could use value 4, but i want to do it elegant.

    Second step was to define listener of specific profile:

    BluetoothProfile.ServiceListener mProfileListener = new BluetoothProfile.ServiceListener() {
            @Override
            public void onServiceConnected(int profile, BluetoothProfile proxy) {
                Log.i("btclass", profile + "");
                if (profile == ConnectToLastBluetoothBarcodeDeviceTask.getInputDeviceHiddenConstans()) {
                    List<BluetoothDevice> connectedDevices = proxy.getConnectedDevices();
                    if (connectedDevices.size() == 0) {
                    } else if (connectedDevices.size() == 1) {
                        BluetoothDevice bluetoothDevice = connectedDevices.get(0);
                        ...
                    } else {
                        Log.i("btclass", "too many input devices");
                    }
                }
    
            }
    
            @Override
            public void onServiceDisconnected(int profile) {
    
            }
        };
    

    In third step I invoked

    mBluetoothAdapter.getProfileProxy(getActivity(), mProfileListener,
                ConnectToLastBluetoothBarcodeDeviceTask.getInputDeviceHiddenConstant());
    

    Everything clearly works and mProfileListener returns me list of specific profile bluetooth device/-es. Most interesting thing takes place in onServiceConnected() method, which returs object of hidden class BluetoothInputDevice :)