Статусы изменения подключения Android BLE Gatt

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

Иногда, если устройство разрывает соединение, я получаю изменение соединения как отключение со значением статуса 19. Также, если есть какая-либо ошибка связи, статус равен 22. Если я программно разрываю соединение, этот статус дает мне 0. Но ни один из эти состояния, за исключением 0, указаны в документации по Android.

Размещение образца BluetoothGattCallback

private BluetoothGattCallback bluetoothGattCallback = new BluetoothGattCallback() {
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
        Log.i(TAG, "onConnectionStateChange status: "+status+", newState: "+newState);
        /*i need to know the posiible values for this status variable*/
        if(newState == BluetoothProfile.STATE_CONNECTED) {
            gatt.discoverServices();
        } else {
            gatt.close();
        }
    }

    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
        Log.i(TAG, "onServicesDiscovered service discovered");
    }
};

Сталкивался ли кто-нибудь с такой же проблемой и перебирал список статусов. Мне нужно знать возможные значения переменной статуса в методе onConnectionStateChange


person Ijas Ahamed N    schedule 12.07.2017    source источник
comment
разместите свой код ..   -  person Dus    schedule 12.07.2017
comment
@Dus Я опубликовал образец кода, так как мой код слишком длинный и не имеет отношения к текущей ситуации   -  person Ijas Ahamed N    schedule 12.07.2017


Ответы (3)


Вот список кодов, которые у меня есть

  • Программно отключен - 0
  • Устройство вышло из зоны действия - 8
  • Отключено устройством - 19
  • Выпуск с облигацией - 22
  • Устройство не найдено - 133 (какой-то телефон дает 62)

Я тестировал сценарий отключения в 5.0.2, 5.1, 6.0 и 6.0.1. Но нашел этот код выпуска облигаций только в версии 6.0.1 android.

person Ijas Ahamed N    schedule 21.07.2017
comment
как решить проблему с ошибкой облигации? следует ли закрыть gatt и восстановить соединение или попытаться повторно подключить существующий gatt? см. мою проблему здесь stackoverflow.com/q/47596419/4111151 - person prasanthMurugan; 06.12.2017
comment
Попробуйте удалить облигацию и повторно выполнить облигацию. Думаю, это решит ошибку облигаций. - person Ijas Ahamed N; 06.12.2017
comment
спасибо, но я не использую облигацию, я использую метод подключения GATT для связи. Вы знаете об этом? - person prasanthMurugan; 06.12.2017
comment
По моему опыту, ошибка 22 будет выдана за ошибку плохой связи. Проверить, подключено ли BluetoothDevice? - person Ijas Ahamed N; 06.12.2017
comment
Вы получите объект BluetoothDevice из объекта BluetoothGatt в GattCallback. Устройство BluetoothDevice = gatt.getDevice (); int bondState = device.getBondState (); Документация developer.android.com/reference/android/bluetooth/ - person Ijas Ahamed N; 06.12.2017
comment
Я тоже получил статус 34. Что это значит? Я не смог найти его в вышеупомянутом URL-адресе. - person Aanal Mehta; 26.10.2018
comment
@AanalMehta У меня еще нет статуса 34. Так что понятия не имею об этом. - person Ijas Ahamed N; 29.10.2018
comment
@AanalMehta Согласно этот файл, 34 может означать сбой подключения из-за тайм-аута ответа LMP. - person Gumby The Green; 29.05.2020
comment
@IjasAhamedN Где вы нашли эти коды ошибок? Я использую SDK, который выдает коды ошибок 13, 34, 133. Я предполагаю, что эти коды ошибок исходят от Android API, которые могут обрабатываться в самом SDK. Но я не знаю, что означают эти коды ошибок и в каком классе они есть. - person Nikhil Bansal; 21.08.2020
comment
@NikhilBansal Я пробовал разные сценарии и сам вычислял эти коды ошибок - person Ijas Ahamed N; 21.08.2020
comment
@IjasAhamedN Я нашел эта ссылка, где определены все коды ошибок. Может быть, это поможет вам больше. Кроме того, я нашел интересный запрос на извлечение GitHub, который может оказаться более полезным. Вы можете найти его здесь. - person Nikhil Bansal; 22.08.2020

Извините, что поднял старый вопрос, но вот решение многих проблем, которые у меня были с Bluetooth (BLE) 4.0. Еще раз извините за большие классы, представленные ниже, но убедитесь, что они необходимы, и что там нет ненужных или неиспользуемых методов.

public abstract class AbstractBluetoothBroadcaster extends BroadcastReceiver {
    protected static final String LOG_TAG = BluetoothLowEnergy.LOG_TAG;

    protected BluetoothLowEnergy bluetoothLowEnergy;

    public AbstractBluetoothBroadcaster(BluetoothLowEnergy bluetoothLowEnergy, String action){
        super();
        this.bluetoothLowEnergy = bluetoothLowEnergy;

        IntentFilter intentFilterStateChange = new IntentFilter(action);
        intentFilterStateChange.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
        this.bluetoothLowEnergy.getActivity().registerReceiver(this, intentFilterStateChange);
    }

    public void onDestroy(){
        this.bluetoothLowEnergy.getActivity().unregisterReceiver(this);
    }
}


public class BluetoothBondStateBroadcaster extends AbstractBluetoothBroadcaster {

    private BluetoothLowEnergy bluetoothLowEnergy;
    private boolean deviceBonded;

    public BluetoothBondStateBroadcaster(BluetoothLowEnergy bluetoothLowEnergy) {
        super(bluetoothLowEnergy, BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        this.bluetoothLowEnergy = bluetoothLowEnergy;
        this.deviceBonded = false;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (action == null){
            return;
        }
        BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
        if (action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED) &&
                bluetoothDevice != null &&
                bluetoothDevice.getAddress().equals(bluetoothLowEnergy.getDeviceUUID())) {
            int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1);
            switch (state) {
                case BluetoothDevice.BOND_NONE:
                    Log.d(LOG_TAG, "  NOT BONDED - dev " + bluetoothDevice.getAddress());
                    this.deviceBonded = false;
                    break;
                case BluetoothDevice.BOND_BONDING:
                    Log.d(LOG_TAG, " BONDING ... - dev " + bluetoothDevice.getAddress());
                    break;
                case BluetoothDevice.BOND_BONDED:
                    Log.d(LOG_TAG, " BONDED - dev " + bluetoothDevice.getAddress());
                    deviceBonded = true;
                    bluetoothLowEnergy.onBluetoothBonded();
                    break;
                default:
                    break;
            }
        }
    }

    public void resetDeviceBonded(){
        this.deviceBonded = false;
    }

    public boolean isDeviceBonded() {
        return deviceBonded;
    }
}


public class BluetoothPairingBroadcaster extends AbstractBluetoothBroadcaster {

    private String devicePIN;

    public BluetoothPairingBroadcaster(BluetoothLowEnergy bluetoothLowEnergy){
        super(bluetoothLowEnergy, BluetoothDevice.ACTION_PAIRING_REQUEST);
        this.devicePIN = "";
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (action == null){
            return;
        }
        BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
        int pairingType = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, BluetoothDevice.ERROR);
        if (action.equals(BluetoothDevice.ACTION_PAIRING_REQUEST) &&
                bluetoothDevice != null &&
                bluetoothDevice.getAddress().equals(bluetoothLowEnergy.getDeviceUUID()) &&
                !getDevicePIN().isEmpty()) {
            if (pairingType == BluetoothDevice.PAIRING_VARIANT_PIN){
                bluetoothDevice.setPin(getDevicePIN().getBytes());
                Log.d(LOG_TAG," Auto-entering pin - " + getDevicePIN());
                bluetoothDevice.createBond();
                Log.d(LOG_TAG," pin entered and request sent...");
                abortBroadcast();
            }
        }
    }

    public void setDevicePIN(String pin){
        this.devicePIN = pin;
    }

    public String getDevicePIN(){
        return this.devicePIN ;
    }
}


public class BluetoothLowEnergy extends BluetoothGattCallback {

    // listener that has the methods that the application (activity)
    // will use to send / receive data, or to reflect the system state 
    // in the UI
    public interface BluetoothListener {
        /**
         * Triggered when the scanning has started successfully
         */
        void onBluetoothStartScan();

        /**
         * Triggered when the scanning stops
         * @param scanResults results of the scanning
         */
        void onBluetoothStopScan(Collection<BluetoothDevice> scanResults);

        /**
         * Triggered when the device is ready to send/receive data
         */
        void onBluetoothConnectionReady();

        /**
         * Triggered when a bluetooth msg is received
         * @param msg message received
         */
        void onBluetoothReceiveMsg(String msg);

        /**
         * Triggered whenever data is send
         * @param success true means data was sent fine to the remote device, false otherwise
         */
        void onBluetoothSend(String data, boolean success);

        /**
         * Triggered if no bluetooth is connected, and we need a connection
         * to send / receive / discover services
         */
        void onBluetoothNotConnected();

    }

    // custom exceptions
    public class BluetoothNotEnabledException extends Exception { }
    public class BluetoothLowEnergyNotSupported extends Exception { }
    public class BluetoothDeviceNotFound extends Exception { }

    // service and characteristic uuids that are going to be used to
    // send / receive data between central and peripheral GATTs
    private static final String SERVICE_UUID = "FFE0-";
    private static final String CHARACTERISTIC_UUID = "FFE1-";

    // timeout for bluetooth scan (in ms)
    public static final int SCAN_TIMEOUT = 5000;

    // BLE LOG TAG
    public static final String LOG_TAG = "BLUETOOTH_BLE";

    // model
    private boolean bluetoothScanning;
    private boolean bluetoothConnected;
    private Map<String, BluetoothDevice> bluetoothScanResults;

    // gui
    private Activity activity;

    // bluetooth
    private BluetoothAdapter bluetoothAdapter;
    private BluetoothLeScanner bluetoothLeScanner;
    private ScanCallback bluetoothScanCallback;
    private BluetoothGatt bluetoothGatt;
    private BluetoothGattCharacteristic characteristic;


    public BluetoothLowEnergy(Activity activity, BluetoothListener bluetoothListener){
        this.activity = activity;
        this.bluetoothListener = bluetoothListener;

        // this keeps track of the scanning and connection states
        this.bluetoothScanning = this.bluetoothConnected = false;

        // keeps track of the scanning results
        this.bluetoothScanResults = new HashMap<>();

        // set bluetooth pairing request and bonded callback
        // these broadcasters will be responsible to detect and validate
        // the bonded state of your device
        this.pairingRequestBroadcaster = new BluetoothPairingBroadcaster(this);
        this.bondedBroadcaster = new BluetoothBondStateBroadcaster(this);

        // set the scan callback methods that will add results to 
        // this.bluetoothScanResults map
        this.bluetoothScanCallback = new ScanCallback() {
            @Override
            public void onScanResult(int callbackType, ScanResult result) {
                super.onScanResult(callbackType, result);
                addScanResult(result);
            }

            @Override
            public void onBatchScanResults(List<ScanResult> results) {
                super.onBatchScanResults(results);
                for (ScanResult result: results) {
                    addScanResult(result);
                }
            }

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

            private void addScanResult(ScanResult result) {
                BluetoothDevice device = result.getDevice();
                String deviceAddress = device.getAddress();
                bluetoothScanResults.put(deviceAddress, device);
                Log.d(LOG_TAG, "Found device " + deviceAddress);
            }
        };

        // Use this to determine whether BLE is supported on the device.
        if (!this.activity.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
            throw new BluetoothLowEnergyNotSupported();
        }
    }

    /**
     * This method should be called when the activity is destroyed
     */
    public void onDestroy(){
        this.bondedBroadcaster.onDestroy();
        this.pairingRequestBroadcaster.onDestroy();
        this.disconnect();
    }

    /**
     * This method is called when we finish pairing/bonding to the device
     */
    public void onBluetoothBonded(){
        // if we have the services already discovered, then we can 
        // send/receive data, to do so we call the bluetooth listener below
        if (servicesDiscovered){
            this.bluetoothListener.onBluetoothConnectionReady();
        // if we know we have a connection established, then we can 
        // discover services
        } else if (bluetoothConnected){
            bluetoothGatt.discoverServices();
        }
    }

    /**
     * This method is called whenever a connection is established or a disconnection happens
     */
    @Override        
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
        super.onConnectionStateChange(gatt, status, newState);

        BluetoothDevice bluetoothDevice = gatt.getDevice();

        // if these conditions == true, then we have a disconnect
        if ( status == BluetoothGatt.GATT_FAILURE ||
                status != BluetoothGatt.GATT_SUCCESS ||
                newState == BluetoothProfile.STATE_DISCONNECTED) {
            Log.d(LOG_TAG, String.format(Locale.getDefault(),
                    "Disconnected from %s (%s) - status %d - state %d",
                    bluetoothDevice.getName(),
                    bluetoothDevice.getAddress(),
                    status,
                    newState
            ));
            this.disconnect();
        // if these conditions == true, then we have a successful connection
        } else if (newState == BluetoothProfile.STATE_CONNECTED) {
            bluetoothConnected = true;
            Log.d(LOG_TAG, String.format(Locale.getDefault(),
                    "Connected to %s (%s) - status %d - state %d",
                    bluetoothDevice.getName(),
                    bluetoothDevice.getAddress(),
                    status,
                    newState
            ));
            // this sleep is here to avoid TONS of problems in BLE, that occur whenever we start 
            // service discovery immediately after the connection is established 
            try {
                Thread.sleep(600);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            gatt.discoverServices();
        }
    }

    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
        super.onServicesDiscovered(gatt, status);
        if (status != BluetoothGatt.GATT_SUCCESS) {
            return;
        }
        // BEGIN - find the service and characteristic that we want (defined as a static attribute 
        // of the BluetoothLowEnergy class)
        Log.d(LOG_TAG, "Discovering services ...");
        BluetoothGattService service = null;
        for (BluetoothGattService serv: gatt.getServices()){
            Log.d(LOG_TAG, "Found service " + serv.getUuid().toString());
            if (serv.getUuid().toString().toUpperCase().contains(SERVICE_UUID)){
                service = serv;
                Log.d(LOG_TAG, "---> Selected service " + serv.getUuid().toString());
                break;
            }
        }
        if (service == null){
            return;
        }
        for (BluetoothGattCharacteristic charac: service.getCharacteristics()){
            Log.d(LOG_TAG, "Found characteristic " + charac.getUuid().toString());
            if (charac.getUuid().toString().toUpperCase().contains(CHARACTERISTIC_UUID)){
                this.characteristic = charac;
                Log.d(LOG_TAG, "---> Selected characteristic " + charac.getUuid().toString());
                break;
            }
        }
        if (this.characteristic == null){
            return;
        }
        Log.d(LOG_TAG, "Setting write and notification to the characteristic ...");
        bluetoothAdapter.cancelDiscovery();
        // END - find the service and characteristic 
        // set that we want to write to the selected characteristic and be notified if
        // it changes (the remote GATT peripheral sends data to the Android's GATT Center)
        this.characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
        gatt.setCharacteristicNotification(this.characteristic, true);
        // we finished service discovery
        this.servicesDiscovered = true;
        // if we have paired/bonded then we are ready to send/receive data            
        if (pairingRequestBroadcaster.getDevicePIN().isEmpty() || bondedBroadcaster.isDeviceBonded()) {
            this.bluetoothListener.onBluetoothConnectionReady();
        }
    }

    @Override
    public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic charac, int status) {
        super.onCharacteristicRead(gatt, charac, status);
        restartDisconnectTimeout();
        if (status != BluetoothGatt.GATT_SUCCESS) {
            return;
        }
        try {
            String characValue = new String(charac.getValue(), CHARSET)
                    .replaceAll(DATA_FILTER_REGEX,"");
            Log.i(LOG_TAG, String.format(Locale.getDefault(),
                    "Characteristic Read - %s",
                    characValue
            ));
            if (charac.getUuid().equals(this.characteristic.getUuid())) {
                this.bluetoothListener.onBluetoothReceiveMsg(characValue);
            }
        } catch (UnsupportedEncodingException e) {
            Log.e(LOG_TAG, "Characteristic Read - Failed to convert message string to byte array");
        }
    }

    @Override
    public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic charac, int status) {
        super.onCharacteristicWrite(gatt, charac, status);
        restartDisconnectTimeout();
        try {
            String characValue = new String(charac.getValue(), CHARSET);
            Log.i(LOG_TAG, String.format(Locale.getDefault(),
                    "Characteristic Write - SUCCESS - %s",
                    characValue
            ));
            bluetoothListener.onBluetoothSend( characValue, (status == BluetoothGatt.GATT_SUCCESS) );
        } catch (UnsupportedEncodingException e) {
            Log.e(LOG_TAG, "Characteristic Write - Failed to convert message string to byte array");
        }
    }


    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic charac) {
        super.onCharacteristicChanged(gatt, charac);
        Log.d(LOG_TAG,"Characteristic Changed");
        onCharacteristicRead(gatt, charac, BluetoothGatt.GATT_SUCCESS);
    }

    /**
     * Remove pairing/bonding of the device 
     * @param device Device to remove bonding
     */
    public static void removeBond(BluetoothDevice device){
        try {
            if (device == null){
                throw new Exception();
            }
            Method method = device.getClass().getMethod("removeBond", (Class[]) null);
            method.invoke(device, (Object[]) null);
            Log.d(LOG_TAG, "removeBond() called");
            Thread.sleep(600);
            Log.d(LOG_TAG, "removeBond() - finished method");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Clears the GATT services cache, so that new services can be discovered 
     * @param bluetoothGatt GATT Client to clear service's discovery cache
     */
    public static void refresh(BluetoothGatt bluetoothGatt){
        try {
            Method method = bluetoothGatt.getClass().getMethod("refresh", (Class[]) null);
            method.invoke(bluetoothGatt, (Object[]) null);
        } catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * Connect to the GATT Peripheral device
     * @param uuid GATT Peripheral address / mac / uuid to connect to
     * @param pin PIN to authenticate and pair to the device
     */
    public void connect(String uuid, String pin) throws BluetoothNotEnabledException, BluetoothDeviceNotFound {
        checkBluetooth();
        // do not connect twice
        if (this.isConnected()){
            return;
        }
        // get device
        BluetoothDevice device = this.bluetoothScanResults.get(uuid);
        if (device == null){
            throw new BluetoothDeviceNotFound();
        }
        this.deviceUUID = uuid;
        pairingRequestBroadcaster.setDevicePIN(pin);
        removeBond(device);
        // create connection to the bluetooth device
        bluetoothGatt = device.connectGatt(activity, false, this);
        refresh(bluetoothGatt);
    }

    /**
     * Disconnect from BLE device. This method should be called whenever we want to 
     * close the APP, or the BLE connection.
     */
    public void disconnect() {            
        Log.d(LOG_TAG, "disconnect() - executed");
        if (bluetoothGatt != null) {
            if (characteristic != null) {
                bluetoothGatt.setCharacteristicNotification(characteristic, false);
            }
            //remove device authorization/ bond/ pairing
            removeBond(bluetoothGatt);
            // disconnect now
            bluetoothGatt.disconnect();
            bluetoothGatt.close();
            Log.d(LOG_TAG, "disconnect() - bluetoothGatt disconnect happened");
        }
        bluetoothGatt = null;
        characteristic = null;
        bluetoothConnected = false;
        servicesDiscovered = false;
        // set device as not bonded anymore
        bondedBroadcaster.resetDeviceBonded();
    }

    /**
     * bluetooth nearby devices scan is on
     * @return true if scanning is on, false otherwise
     */
    public boolean isScanning(){
        return (this.bluetoothScanning);
    }

    /**
     * Check bluetooth system state (on or off)
     * @return true if system is on, false otherwise
     */
    public boolean isEnabled(){
        try {
            checkBluetooth();
            return bluetoothAdapter.isEnabled();
        } catch (BluetoothNotEnabledException e) {
            return false;
        }
    }

    /**
     * Check bluetooth connection
     * @return true if connected, false otherwise
     */
    public boolean isConnected(){
        return (this.bluetoothConnected);
    }

    /**
     * Start bluetooth scan for nearby devices
     * @param filters Scan filters that define what devices to scan for
     */
    public void startScan(List<ScanFilter> filters)
            throws BluetoothNotEnabledException{
        checkBluetooth();
        // dont run two scans simultaneously
        if (isScanning()) {
            return;
        }
        // disconnect previously connected devices
        if (isConnected()) {
            this.disconnect();
            return;
        }
        // setup bluetooth scanning settings
        ScanSettings settings = new ScanSettings.Builder()
                .setScanMode(ScanSettings.SCAN_MODE_LOW_POWER)
                .build();

        // start scanning
        this.bluetoothScanning = true;
        this.bluetoothScanResults.clear();
        this.bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();

        // Stops scanning after a pre-defined scan period.
        Handler bluetoothHandler = new Handler();
        bluetoothHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                stopScan();
            }
        }, SCAN_TIMEOUT);

        // start scan with default scan callback
        this.bluetoothLeScanner.startScan(filters, settings, bluetoothScanCallback);
        // we have started successfully the BLE scanning
        bluetoothListener.onBluetoothStartScan();
    }

    /**
     * Stop bluetooth scan for nearby devices
     */
    public void stopScan(){
        if (!bluetoothScanning) {
            return;
        }
        // set app scan state to false
        bluetoothScanning = false;
        if (bluetoothLeScanner != null) {
            bluetoothLeScanner.stopScan(bluetoothScanCallback);
            bluetoothLeScanner = null;
        }
        // we have stopped BLE scanning, call the user's callback
        bluetoothListener.onBluetoothStopScan(bluetoothScanResults.values());
    }

    /**
     * Send a message via bluetooth
     * @param msg message to send
     */
    public void send(String msg) {
        if (!bluetoothConnected || characteristic == null){
            bluetoothListener.onBluetoothNotConnected();
            return;
        }
        try {
            msg = msg.replaceAll(DATA_FILTER_REGEX, "") + TERMINATION_CHAR;
            Log.d(LOG_TAG, String.format(Locale.getDefault(),
                    "Sending message: %s",
                    msg));
            characteristic.setValue(msg.getBytes(CHARSET));
            bluetoothGatt.writeCharacteristic(characteristic);
        } catch (UnsupportedEncodingException e) {
            Log.e(LOG_TAG,
                "BluetoothLowEnergy.send: Failed to convert message string to byte array");
        }
    }

    public String getDeviceUUID(){
        return deviceUUID;
    }

    public Activity getActivity(){
        return activity;
    }

    /**
     * Check if bluetooth is enabled and working properly
     */
    private void checkBluetooth() throws BluetoothNotEnabledException{
        if (bluetoothAdapter == null) {
            final BluetoothManager bluetoothManager =
                    (BluetoothManager) activity.getSystemService(Context.BLUETOOTH_SERVICE);
            if (bluetoothManager == null){
                throw new BluetoothNotEnabledException();
            }
            bluetoothAdapter = bluetoothManager.getAdapter();
        }

        // Ensures Bluetooth is available on the device and it is enabled. If not,
        // displays a dialog requesting user permission to enable Bluetooth.
        if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) {
            throw new BluetoothNotEnabledException();
        }
    }

}

Ключевые методы и функции, позволяющие избежать проблем, использованные выше:

  • Thread.sleep(600)
  • removeBond(device)
  • refresh(gatt)
  • gatt.disconnect()
  • gatt.close()
person Andre Madureira    schedule 09.10.2018
comment
Это интересный дамп кода, но в нем можно было бы пояснить, как избежать ошибок 19 и 22. - person Casey Perkins; 21.05.2019
comment
Спасибо, что поделился. Я добавил несколько вещей в свой код на его основе. Я также заметил пару мелочей, которые кажутся излишними: status == BluetoothGatt.GATT_FAILURE и вызов super для переопределенных методов BluetoothGattCallback. - person Gumby The Green; 30.05.2020

В моем случае я получил этот ответ от стека bluetooth, потому что устройство уже было связано с моим телефоном. Я удалил его из своих настроек, и ошибка 22 исчезла.

person Nicola Gallazzi    schedule 16.01.2019