Соединение с устройством Bluetooth LE занимает слишком много времени Android - PullRequest
0 голосов
/ 29 февраля 2020

Как видно из названия, я пытаюсь найти самый быстрый способ подключения к устройству Bluetooth LE без каких-либо проблем. До сих пор у меня работало создание нового потока и подключение к устройству, обнаруженному в onLeScan. Этот метод хорошо работает на моем galaxy S9 и galaxy Tab a, так как каждое соединение работает параллельно с другим, что приводит к нахождению устройства за короткое время. Но я не могу получить такой же результат на моей Motorola G4. Даже если сканируются и подключаются только два устройства, иногда требуется более 15-20 секунд, прежде чем вызывается onConnectionStateChange. Похоже, что один экземпляр Гатта ожидает завершения другого sh.

Другой метод, который я пробовал, - это последовательное подключение к каждому устройству, и, если UUID службы устройства совпадает, я подключусь к этому. устройство. Проблема в этом ожидании подключения к таймауту (то есть onConnectionStateChange называется). Обходной путь, который я попытался, состоит в том, чтобы вызвать gatt.close() через 2 секунды после того, как был вызван connectGatt(). Это хорошо работает, если устройство, которое принудительно отключено, не является целевым устройством. Однако, если я принудительно отключу, когда целевое устройство подключается, я больше не могу подключиться к нему снова (иногда), так как он не будет отображаться в списке отсканированных устройств.

Ваш ввод приветствуется.

Вот соответствующий код:

Это одновременный метод подключения.

@Override
    public void onLeScan(final BluetoothDevice device, final int rssi, byte[] scanRecord) {


        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                if (!deviceList.contains(device) && rssi <= -15 && rssi >= -80) {

                    if (connectModeAuto && mBluetoothGatt == null) {
                        Log.d(TAG, "Device name xxx:" + device.getName() + " uuid:" + device.getAddress() + " " + rssi);
                        connectToDevice(device);
                    }
                }
            }
        });
        t.start();
    }

public void connectToDevice(BluetoothDevice device) {

        Log.d(TAG,"Connecting to device xxx");
        Method connectGattMethod;
        mBluetoothGatt = null;
        BluetoothGatt gatt;
        ///*
        try {

            connectGattMethod = device.getClass().getMethod("connectGatt", Context.class, boolean.class, BluetoothGattCallback.class, int.class);

            try {
                gatt = (BluetoothGatt) connectGattMethod.invoke(device, this, false, mGattCallback, 2); // (2 == LE, 1 == BR/EDR)
                gattList.add(gatt);
            } catch (IllegalAccessException e) {
                //IllegalAccessException
            } catch (IllegalArgumentException e) {
                //IllegalArgumentException
            } catch (InvocationTargetException e) {
                //InvocationTargetException
            }
            disconnected = false;
            gattConnect = false;

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

Это альтернативный способ подключения к устройству

   public void connectToDevice(int index,int type) {

        BluetoothDevice device = deviceList.get(index);
        Method connectGattMethod;

        try {
            connectGattMethod = device.getClass().getMethod("connectGatt", Context.class, boolean.class, BluetoothGattCallback.class, int.class);

            try {
                mBluetoothGatt = (BluetoothGatt) connectGattMethod.invoke(device, this, autoConnect, mGattCallback, 2); // (2 == LE, 1 == BR/EDR)
                //gattList.add(0,gatt);
            } catch (IllegalAccessException e) {
                //IllegalAccessException
            } catch (IllegalArgumentException e) {
                //IllegalArgumentException
            } catch (InvocationTargetException e) {
                //InvocationTargetException
            }
            disconnected = false;
            gattConnect = false;
            timeoutThread = null;
            timeoutThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(connectTimeout);
                    } catch (InterruptedException e) {
                        Log.d(TAG,"interrupted xxx");
                        e.printStackTrace();
                        return;
                    }
                    if (!gattConnect) {
                        Log.d(TAG,"xxx Forcing disconnect");
                        disconnected = true;
                        mBluetoothGatt.disconnect();
                        mBluetoothGatt.close();
                        mBluetoothGatt = null;

                        if (deviceList.size() > 0) {
                            retryConnection();
                        } else {
                            scanLeDevice(true);
                        }
                    }
                }
            });
            timeoutThread.start();

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

public void retryConnection() {

        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {

                deviceList.remove(0);
                if (deviceList.size() > 0) {

                    Log.d(TAG,"Have more devices "+deviceList.size());
                    connectToDevice(0,1);
                }
                else {
                    Log.d(TAG,"search mode");
                    scanLeDevice(shouldScan);
                }
            }
        });
        t.start();
    }

public void scanLeDevice(final boolean enable) {
        if (enable) {
            scanning = true;
            // Stops scanning after a pre-defined scan period.
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    mBluetoothAdapter.stopLeScan(mLeScanCallback);

                    Set<BluetoothDevice> set = new HashSet<>(deviceList);
                    deviceList.clear();
                    deviceList.addAll(set);

                    if (deviceList.size() > 0) {

                        if (connectModeAuto) {
                            Thread t2 = new Thread(new Runnable() {
                                @Override
                                public void run() {
                                    connectToDevice(0,1); // Connect to first device found.
                                }
                            });
                            t2.start();
                        }
                    }

                }
            }, 3000);

            boolean scanDidStart = mBluetoothAdapter.startLeScan(mLeScanCallback);
            //UUID[] uuids = {SERVICE_UUID};
            //mBluetoothAdapter.startLeScan(uuids,mLeScanCallback);

            if (scanDidStart) {
                Log.d(TAG, "Scan started");
            } else {
                Log.d(TAG, "Scan did not start");
            }
        } else {
            scanning = false;
            mBluetoothAdapter.stopLeScan(mLeScanCallback);
        }
    }
...