Android BLE Scan никогда не находит устройства - PullRequest
0 голосов
/ 18 декабря 2018

Уже несколько дней я пытаюсь реализовать соединение BLE в своем приложении.Я знаю, что устройство, с которым я пытаюсь подключиться, полнофункционально, поэтому проблема заключается в моем коде.

Я использую метод BluetoothLeScanner.startScan().
Но метод обратного вызова никогда не вызывается.

   public void startScan() {
        if (bluetoothAdapter != null && bluetoothAdapter.isEnabled()) {
            isScanning = true;
            Handler mHandler = new Handler();
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    mainActivityHandler.setMSG("Scan stopped");
                    isScanning = false;
                    leScanner.stopScan(scanCallback);
                }
            }, SCAN_TIME);

            mainActivityHandler.setMSG("Start scan");

            try {

                leScanner.startScan(scanCallback);
            } catch (Exception e) {
                mainActivityHandler.catchError(e);
            }

        } else mainActivityHandler.catchError(new Exception("Bluetooth not activated"));
    }

Мой CallbackMethod (не знаю, правильно ли я использую gatt, но это другой вопрос):

    private ScanCallback scanCallback = new ScanCallback() {


    @Override
    public void onBatchScanResults(List<ScanResult> results) {
        mainActivityHandler.setMSG("Callback");
        isScanning = false;
        try {

            mainActivityHandler.setMSG("Connected to " + results.get(0).getDevice().getName());
            gatt = results.get(0).getDevice().connectGatt(mainActivity, true, bluetoothGattCallback);

            BluetoothGattDescriptor descriptor;
            for (int i = 0; i < charIDs.length; i++) {
                gatt.setCharacteristicNotification(gatt.getService(serviceID[0]).getCharacteristic(charIDs[i]), true);

                descriptor = gatt.getService(serviceID[0]).getCharacteristic(charIDs[0]).getDescriptor(charIDs[i]);
                descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                gatt.writeDescriptor(descriptor);
            }
        } catch (Exception e) {
            mainActivityHandler.catchError(e);
        }

    }
};

Ответы [ 2 ]

0 голосов
/ 18 декабря 2018

Проблема

Проблема в том, что вы переопределяете только метод onBatchScanResults, а не onScanResult.onBatchScanResults сработает только в том случае, если:

  1. Вы установили режим ScanSettings на ScanSettings.SCAN_MODE_LOW_POWER (это значение по умолчанию), используя ScanSettings.Builder.
  2. .установите время задержки отчета на некоторое значение> 0, используя setReportDelay(long reportDelayMillis) в вашем ScanSettings.Builder.

reportDelayMillis - Задержка отчета вмиллисекунды.Установите 0, чтобы получать уведомления о результатах немедленно.При значениях> 0 результаты сканирования ставятся в очередь и доставляются после запрошенной задержки или после заполнения внутренних буферов.

Например:

public void startScan(BluetoothLeScanner scanner) {
    ScanFilter filter = new ScanFilter.Builder().setDeviceName(null).build();

    ArrayList<ScanFilter> filters = new ArrayList<ScanFilter>();
                    filters.add(filter);

    ScanSettings settings = new ScanSettings.Builder()
                                .setScanMode(ScanSettings.SCAN_MODE_LOW_POWER)
                                .setReportDelay(1l)
                                .build();

    Log.i(TAG,"The setting are "+settings.getReportDelayMillis());
    scanner.startScan(filters,settings,BLEScan);
}

Решение

Однако вы, вероятно, просто хотите получать результаты по одному за раз, а не партию результатов.Для этого вам не нужно изменять ScanSettings, вам просто нужно переопределить метод onScanResult в вашем ScanCallback, и это поможет.

private ScanCallback mScanCallback =
        new ScanCallback() {

    public void onScanResult(int callbackType, ScanResult result) {
        System.out.println(result.getDevice().getName())
        // Do whatever you want
    };

    ...
};

Альтернатива - RxAndroidBle

В любом случае, я настоятельно рекомендую использовать библиотеку RxAndroidBle .Он очень хорошо поддерживается и решает многие проблемы BLE из коробки (сканирование, возможно, является менее сложной частью в BLE).

Используя эту библиотеку, сканирование можно выполнить следующим образом:

Disposable scanSubscription = rxBleClient.scanBleDevices(


    new ScanSettings.Builder()
            // .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) // change if needed
            // .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES) // change if needed
            .build()
        // add filters if needed
)
    .subscribe(
        scanResult -> {
            // Process scan result here.
        },
        throwable -> {
            // Handle an error here.
        }
    );

// When done, just dispose.
scanSubscription.dispose();
0 голосов
/ 18 декабря 2018

Контрольный список:

У вас включено местоположение, убедитесь, что оно включено специально для устройств после Api 23. Также есть бесплатное приложение nrfconnect (что-то, что я использовал) Пожалуйста, скачайте его и посмотрите егообнаруживает устройство.

Также это то, что я использовал

private void startScan() {
        try {
            if (!hasPermissions() || mScanning) {
                return;
            }

            List<ScanFilter> filters = new ArrayList<>();
            ScanSettings settings = new ScanSettings.Builder()
                    .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
                    .build();
            mScanResults = new ArrayList<>();
            mScanCallback = new DeviceScanCallback();
            mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
            handleProgress(true, getString(R.string.lbl_scanning));
            mBluetoothLeScanner.startScan(filters, settings, mScanCallback);
            mScanning = true;
            final Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (activity == null || !isAdded()) {
                        return;
                    }
                    if (getResources() != null) {
                        handleProgress(false, getResources().getString(R.string.lbl_scanning));
                        stopScan();
                    }
                }
            }, 20000);
        } catch (Exception e) {
            Toast.makeText(activity, getString(R.string.scan_failed), Toast.LENGTH_LONG).show();
            e.printStackTrace();
        }
    }

// Класс для использования обратного вызова

     private class DeviceScanCallback extends ScanCallback {

        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            try {
                if (result != null && result.getScanRecord() != null && result.getScanRecord().getDeviceName() != null) {
                    Log.d("Device name", "" + result.getScanRecord().getDeviceName());
                    if (result.getScanRecord().getDeviceName().startsWith(ConstantClass.DEVICE_IDENTIFIER)) {
                        addScanResult(result);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onBatchScanResults(List<ScanResult> results) {
            try {
                for (ScanResult result : results) {
                    Log.i("ScanResult - Results", result.toString() + " " + result.getDevice().getName());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onScanFailed(int errorCode) {
            Log.e(TAG, "BLE Scan Failed with code " + errorCode);
        }

        private void addScanResult(ScanResult result) {
            try {
                BluetoothDevice device = result.getDevice();
                if (mScanResults != null) {
                    mScanResults.add(device);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
}
...