Bluetooth LE peripheral stop advertising on connec

2019-02-15 01:49发布

问题:

I want to develop app like Bluetooth LE peripheral device which stop advertising on connect with Bluetooth LE central device and restrict Bluetooth LE peripheral device which connects with multiple Bluetooth LE central.

One Bluetooth LE peripheral device only connect with one Bluetooth LE central at a time. Other Bluetooth LE central device could not scan after successfully connection of Bluetooth LE peripheral and Bluetooth LE central

Till now i try below code:

private final BluetoothGattServerCallback mGattServerCallback = new BluetoothGattServerCallback() {

        @Override
        public void onServiceAdded(int status, BluetoothGattService service) {
                                                                                                            super.onServiceAdded(status, service);
        }

        @Override
        public void onConnectionStateChange(BluetoothDevice device, final int status, int newState) {
            super.onConnectionStateChange(device, status, newState);
            if (status == BluetoothGatt.GATT_SUCCESS) {
                if (newState == BluetoothGatt.STATE_CONNECTED) {
                    mBluetoothDevices.add(device);

                    // Bluetooth LE peripheral stop advertising on connect with Bluetooth LE central device
                    mAdvertiser.stopAdvertising(mAdvCallback);

                    Log.v(TAG, "Connected to device: " + device.getAddress());
                } else if (newState == BluetoothGatt.STATE_DISCONNECTED) {
                    mBluetoothDevices.remove(device);
                    Log.v(TAG, "Disconnected from device");
                }
            } else {
                mBluetoothDevices.remove(device);
                // There are too many gatt errors (some of them not even in the documentation) so we just
                // show the error to the user.
                final String errorMessage = getString(R.string.status_errorWhenConnecting) + ": " + status;
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(MainActivity.this, errorMessage, Toast.LENGTH_LONG).show();
                    }
                });
                Log.e(TAG, "Error when connecting: " + status);
            }
        }

        @Override
        public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset,
                                                BluetoothGattCharacteristic characteristic) {
        }

        @Override
        public void onNotificationSent(BluetoothDevice device, int status) {
            super.onNotificationSent(device, status);
            Log.v(TAG, "Notification sent. Status: " + status);
        }

        @Override
        public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId,
                                                 BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
        }

        @Override
        public void onDescriptorWriteRequest(BluetoothDevice device, int requestId,
                                             BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded,
                                             int offset,
                                             byte[] value) {
        }
    };

I am stopAdvertising on connect with BLE central device mAdvertiser.stopAdvertising(mAdvCallback);

It is disconnect connection.

Please help me in this use case. THANKS IN ADVANCE

回答1:

Put BluetoothGattServer.connect(BluetoothDevice device, boolean autoConnect) in BluetoothGatt.STATE_CONNECTED before stopAdvertising, because expected Android framework behavior. If you need to continue to hold the link and don't want to advertise anymore, you need to call into additional connect()

Code snippet of Solution

//******************* SOLUTION **************************
        BluetoothDevice mDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(device.getAddress());
        mGattServer.connect(mDevice, false);
//*******************************************************

Code snippet of onConnectionStateChange() implementation

@Override
public void onConnectionStateChange(BluetoothDevice device, final int status, int newState) {
    super.onConnectionStateChange(device, status, newState);
    if (status == BluetoothGatt.GATT_SUCCESS) {
        if (newState == BluetoothGatt.STATE_CONNECTED) {
            mBluetoothDevices.add(device);

//******************* SOLUTION **************************
        BluetoothDevice mDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(device.getAddress());
        mGattServer.connect(mDevice, false);
//*******************************************************

            // Bluetooth LE peripheral stop advertising on connect with Bluetooth LE central device
            mAdvertiser.stopAdvertising(mAdvCallback);

            Log.v(TAG, "Connected to device: " + device.getAddress());
        } else if (newState == BluetoothGatt.STATE_DISCONNECTED) {
            mBluetoothDevices.remove(device);
            Log.v(TAG, "Disconnected from device");
        }
    } else {
        mBluetoothDevices.remove(device);
        // There are too many gatt errors (some of them not even in the documentation) so we just
        // show the error to the user.
        final String errorMessage = getString(R.string.status_errorWhenConnecting) + ": " + status;
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(MainActivity.this, errorMessage, Toast.LENGTH_LONG).show();
            }
        });
        Log.e(TAG, "Error when connecting: " + status);
    }
}