Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to programmatically pair and connect a HID bluetooth device(Bluetooth Keyboard) on Android

I am able to pair a bluetooth keyboard but not able to connect so as to make it an input device. I went through the documentation provided at developer site - http://developer.android.com/guide/topics/connectivity/bluetooth.html#Profiles

It says that the Android Bluetooth API provides implementations for the following Bluetooth profiles but you can implement the interface BluetoothProfile to write your own classes to support a particular Bluetooth profile.

  • Headset
  • A2DP
  • Health Device

There is no documentation how to implement BluetoothProfile for HID bluetooth device(Keyboard)

Android has itself implemented bluetooth connection for HID devices but those API's are hidden. I tried reflection to use them too. I do not get any error but keyboard does not get connected as input device. This is what i have done -

private void connect(final BluetoothDevice bluetoothDevice) {
    if(bluetoothDevice.getBluetoothClass().getDeviceClass() == 1344){
        final BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
            BluetoothProfile.ServiceListener mProfileListener = new BluetoothProfile.ServiceListener() {
                @Override
                public void onServiceConnected(int profile, BluetoothProfile proxy) {
                    Log.i("btclass", profile + "");

                    if (profile == getInputDeviceHiddenConstant()) {
                        Class instance = null;
                        try {
                            //instance = Class.forName("android.bluetooth.IBluetoothInputDevice");
                            instance = Class.forName("android.bluetooth.BluetoothInputDevice");
                            Method connect = instance.getDeclaredMethod("connect", BluetoothDevice.class);
                            Object value = connect.invoke(proxy, bluetoothDevice);
                            Log.e("btclass", value.toString());
                        } catch (ClassNotFoundException e) {
                            e.printStackTrace();
                        } catch (InvocationTargetException e) {
                            e.printStackTrace();
                        } catch (NoSuchMethodException e) {
                            e.printStackTrace();
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }



                    }
                }

                @Override
                public void onServiceDisconnected(int profile) {

                }
            };

            mBluetoothAdapter.getProfileProxy(this, mProfileListener,getInputDeviceHiddenConstant());


    }

}

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("", e.toString(), e);
            }
        }
    }
    return -1;
}
like image 218
Passiondroid Avatar asked Mar 15 '16 08:03

Passiondroid


People also ask

Can I connect a Bluetooth keyboard to my android phone?

Bluetooth Keyboard to Android – PairingYou can pair a bluetooth keyboard easily, as you pair any bluetooth device. First, go to Settings and enable Bluetooth in your device. Then, your phone or tablet will detect the available Bluetooth keyboard and pairing will be done almost automatically.

What is Bluetooth HID mode?

HID (Human Interface Device) is the USB protocol that is used by a conventional keyboard and mouse. HID proxy mode allows a Bluetooth keyboard and mouse to function without loading the Bluetooth HCI driver. With HID proxy mode, the computer believes it is interacting with a conventional keyboard or mouse.

What is android HID device?

The head tracker human interface device (HID) protocol, available for devices running Android 13 and higher, allows for a head-tracking device to be connected to an Android device through USB or Bluetooth and be exposed to the Android framework and apps through the sensors framework.


2 Answers

Due to security reasons, it is not possible for third party applications to connect to a bluetooth keyboard as the application can be a keylogger. So it can be only done manually by the user.

like image 86
Passiondroid Avatar answered Sep 19 '22 16:09

Passiondroid


Here is the code I used on Android Marshmallow (6.0).. To get an L2CAP connection started (Needed for HID)

public static BluetoothSocket createL2CAPBluetoothSocket(String address, int psm){
    return createBluetoothSocket(BluetoothSocket.TYPE_L2CAP, -1, false,false, address, psm);
}

// method for creating a bluetooth client socket
private static BluetoothSocket createBluetoothSocket(int type, int fd, boolean auth, boolean encrypt, String address, int port){
    Log.e(TAG, "Creating socket with " + address + ":" + port);

    try {
        Constructor<BluetoothSocket> constructor = BluetoothSocket.class.getDeclaredConstructor(
                int.class, int.class,boolean.class,boolean.class,String.class, int.class);
        constructor.setAccessible(true);
        BluetoothSocket clientSocket = (BluetoothSocket) constructor.newInstance(type,fd,auth,encrypt,address,port);
        return clientSocket;
    }catch (Exception e) {
        e.printStackTrace();
    }

    return null;
}

public Boolean connect(View v) {

    try {
        // TODO: Check bluetooth enabled
        mDevice = getController();

        if (mDevice != null) {
            Log.e(TAG, "Controller is paired");

            // Create socket
            mSocket = createL2CAPBluetoothSocket(mDevice.getAddress(), 0x1124);

            if (mSocket != null) {

                if (!mSocket.isConnected()) {
                    mSocket.connect();
                }

                Log.e(TAG, "Socket successfully created");

                ConnectedThread mConnectedThread = new ConnectedThread(mSocket);
                mConnectedThread.run();
            }

        } else {
            showToast("Controller is not connected");
        }

        return true;

    } catch (Exception e) {
        e.printStackTrace();

        if (e instanceof IOException){
            // handle this exception type
        } else {
            // We didn't expect this one. What could it be? Let's log it, and let it bubble up the hierarchy.

        }

        return false;
    }
}

private BluetoothDevice getController() {
    Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();

    if (pairedDevices.size() > 0) {
        for (BluetoothDevice device : pairedDevices) {
            if (device.getName().equals("Wireless Controller"))    // Change to match DS4 - node name
            {
                Log.d(TAG, "Found device named: " + device.getName());

                return device;
            }
        }
    }

    return null;
}

It can still have problems creating the Service, and you need to set the correct L2CAP PSAM for the device, but hope it can help..

like image 42
DutchKevv Avatar answered Sep 20 '22 16:09

DutchKevv