Android Bluetooth Paring Input Device

2.1k views Asked by At

I am trying to make a pairing by code and it works only for normal devices. If I use a bluetooth scanner it pairs with it but the device doesn't work till I go to android settings and select the Input Device checkbox. How can I do this by code?

Thank you.

Here is my pairing code:

public static BluetoothSocket createL2CAPBluetoothSocket(String address, int psm){
    return createBluetoothSocket(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){
    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) { return null; }
}

private void doPair(final BluetoothDevice device, final int deviceTag) {
    try {
        Method method = device.getClass().getMethod("createBond",
                (Class[]) null);
        method.invoke(device, (Object[]) null);
    } catch (Exception e) {
        Log.e(LOG_TAG, "Cannot pair device", e);
    }

    BroadcastReceiver mReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();

            if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
                final int state = intent.getIntExtra(
                        BluetoothDevice.EXTRA_BOND_STATE,
                        BluetoothDevice.ERROR);
                final int prevState = intent.getIntExtra(
                        BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE,
                        BluetoothDevice.ERROR);

                if (state == BluetoothDevice.BOND_BONDED
                        && prevState == BluetoothDevice.BOND_BONDING) {
                    Log.d(LOG_TAG, "Paired with new device");
                    if (listener != null) {
                        listener.onBluetoothPairedDeviceChange(bluetoothAdapter
                                .getBondedDevices().iterator().next()
                                .getName(), deviceTag);
                    }
                    context.unregisterReceiver(this);
                } else if (state == BluetoothDevice.BOND_NONE
                        && prevState == BluetoothDevice.BOND_BONDING) {
                    Log.d(LOG_TAG, "Cannot pair with new device");
                    if (listener != null) {
                        listener.onBluetoothStatusChange(BluetoothHelper.IDLE_STATUS);
                    }
                    context.unregisterReceiver(this);
                }
            }
        }

    };

    IntentFilter intent = new IntentFilter(
            BluetoothDevice.ACTION_BOND_STATE_CHANGED);
    context.registerReceiver(mReceiver, intent);
}
1

There are 1 answers

1
qianlv On

First,if your target version after API 19 , you can use BluetoothDevice.createBond() to pair the device directly without use reflection. Following methods only work on devices before android 6.0!(After 6.0, system will do some caller check to avoid outer app to call these methods)

 BluetoothAdapter.getDefaultAdapter().getProfileProxy(MainActivity.this, new BluetoothProfile.ServiceListener() {
     @Override
     public void onServiceConnected(int profile, BluetoothProfile proxy) {
          Class<?> clazz = null;
          try {
               clazz = Class.forName("android.bluetooth.BluetoothInputDevice");
               Object obj = clazz.cast(proxy);
               Method connectMethod = clazz.getDeclaredMethod("connect",BluetoothDevice.class);
               boolean resultCode = (boolean) connectMethod.invoke(obj,device);
               Method setPriority = clazz.getDeclaredMethod("setPriority",BluetoothDevice.class,int.class);
               setPriority.invoke(obj,device,1000);
          } catch (ClassNotFoundException e) {
               e.printStackTrace();
          } catch (NoSuchMethodException e) {
               e.printStackTrace();
          } catch (InvocationTargetException e) {
               e.printStackTrace();
          } catch (IllegalAccessException e) {
               e.printStackTrace();
          }
     }

     @Override
     public void onServiceDisconnected(int profile) {
             Log.d("wtf","onservice disconnected "+profile);
     }
},INPUT_DEVICE);

final int INPUT_DEVICE = 4; // this is hidden memeber in BluetoothDevice