Android Low Power Bluetooth Multi-Device Connection and Data Receiving, Simple Implementation

Keywords: Android Mobile

Unconsciously, it's almost two weeks since I worked overtime all night. I haven't worked like that for nearly two years.

The reason is a function of the project, Bluetooth multi-connection. The application connects multiple devices at the same time, waits for receiving data, and displays the chart after processing.

I haven't done anything about Bluetooth before, so I have to start from the basics and work at the same time.


At first I didn't know. I was looking at the connection and transmission of traditional Bluetooth. A few days later, I found that it was different from low-power Bluetooth. I started looking for information about low-power Bluetooth.


The lowest api supported by low power Bluetooth is 18.

Basic idea: There are two kinds of low power Bluetooth connection, one is as peripheral equipment, the other is as central equipment. Because the requirement is multi-connection, we deal with it by creating a central device.


Let's first record a low-power Bluetooth connection:

Note: Because the program and hardware are a set of devices, so I do not need to scan the nearby equipment, and then choose the connection, directly connect with the address.


Bluetooth requires permissions:

 <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />


If you want your application to support low-power Bluetooth only, add a privilege:

 <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>


Next in activity, we need to get both peripheral and central devices: Bluetooth Manager and Bluetooth Adapter:

//Get Bluetooth Manager
        BluetoothManager mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        //Get Bluetooth Adapter
        BluetoothAdapter mBluetoothAdapter = mBluetoothManager.getAdapter();

        //If Bluetooth is not turned on, open Bluetooth
        if (!mBluetoothAdapter.isEnabled()) {
            mBluetoothAdapter.enable();
        }


Then you get the BluetoothDevice object from the adapter above:

BluetoothDevice bluetoothDeviceOne = mBluetoothAdapter.getRemoteDevice("D8:B0:4C:BC:C0:83");

Note: 1. The incoming parameter is your Bluetooth address.

2. If you need more connections, you need to get multiple BluetoothDevice objects through different addresses.


Then there's the Bluetooth Gatt object:

private BluetoothGatt mBluetoothGattOne;

After getting the above two objects, check whether the gatt object is running:

//If Gatt is running, close it
        if (mBluetoothGattOne != null) {
            mBluetoothGattOne.close();
            mBluetoothGattOne = null;
        }

Then connect the device and set the callback of the connection:

//Connect Bluetooth Devices and Get Gatt Objects
        mBluetoothGattOne = bluetoothDeviceOne.connectGatt(MainActivity.this, true, bluetoothGattCallbackOne);

Among them, Bluetooth GattCallbackOne is a callback:

/**
     * Bluetooth Return Data Function for the First Device
     */
    private BluetoothGattCallback bluetoothGattCallbackOne = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                if (newState == BluetoothProfile.STATE_CONNECTED) {
                    setText("Successful device-to-device connection");

                    //Search Service
                    gatt.discoverServices();
                } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                    setText("Equipment disconnected");
                }
            }
            super.onConnectionStateChange(gatt, status, newState);
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            //Get Characteristic in Service from UUID and pass it into Gatt
            BluetoothGattService bluetoothGattService = gatt.getService(UUID_SERVICE);
            BluetoothGattCharacteristic bluetoothGattCharacteristic = bluetoothGattService.getCharacteristic(UUID_NOTIFY);

            boolean isConnect = gatt.setCharacteristicNotification(bluetoothGattCharacteristic, true);
            if (isConnect){

            }else {
                Log.i("geanwen", "onServicesDiscovered: Device-to-device connection notify fail");
            }
            super.onServicesDiscovered(gatt, status);
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {//Data change
            super.onCharacteristicChanged(gatt, characteristic);
            String data = new String(characteristic.getValue());
            Log.i("geanwen", "onCharacteristicChanged: " + data);
        }
    };

Note: 1. My requirement is to receive data sent by Bluetooth. If you need to write data or other functions, you can copy the corresponding method in the callback above.

2. The onConectionStateChange method above is the method of callback when the connection state changes, in which the success of the connection is judged.

3. The onServicesDiscovered method above discovers the Bluetooth service after the onConectionStateChange connection is successful.

Here you can set up the services you need, each Bluetooth connection will have different services, you can set up the services you need.

4. Above I set up a service to receive data. Several constants are fixed codes for our low-power Bluetooth service. Here is an example.

//UUID of Bluetooth Service
    public final static UUID UUID_SERVICE = UUID.fromString("0003cdd0-0000-1000-8000-00805f9b0131");

    //UUID for Notfy of Bluetooth Device
    public final static UUID UUID_NOTIFY = UUID.fromString("0003cdd1-0000-1000-8000-00805f9b0131");

Look carefully, the two codes are different. At first, I thought they were the same. The result was adjusted for a long time.

Because my requirement is not to search, connect, and then select the corresponding services, so I omitted these operations, that is, I got the codes of these services in advance.

5. The above callback method onCharacteristicChanged method is the method to receive the data.

Connecting a low-power Bluetooth and receiving data is described above. Next, connect two or more.

First of all, the BluetoothDevice object is mentioned above. When connecting two objects, you need to create a second one:

 BluetoothDevice bluetoothDeviceOne = mBluetoothAdapter.getRemoteDevice("D8:B0:4C:BC:C0:83");
        BluetoothDevice bluetoothDeviceTwo = mBluetoothAdapter.getRemoteDevice("D8:B0:4C:BA:D5:9D");

The next step is the gatt object:

private BluetoothGatt mBluetoothGattOne;
    private BluetoothGatt mBluetoothGattTwo;

//Connect Bluetooth Devices and Get Gatt Objects
        mBluetoothGattOne = bluetoothDeviceOne.connectGatt(MainActivity.this, true, bluetoothGattCallbackOne);
        mBluetoothGattTwo = bluetoothDeviceTwo.connectGatt(MainActivity.this, true, bluetoothGattCallbackTwo);

Next, we wait in the callback, which is no different from the callback above.


Note:

1. The method mentioned above, I connected four devices at the same time, can receive data at the same time.

2. After the application is closed, when it is open, sometimes it will not receive data. The hardware or software is under investigation when the specific problem arises. Reboot Bluetooth on your phone, and it will be all right in a moment.

3. The above program should not succeed on Huawei mobile phone, nor Huawei tablet. (Eggache, the mobile phone I'm testing is Samsung Notee2)

4. The above procedure does not apply for permission for version 6.0 or above.

5. This article is a few days to find information, patchwork out, there may be any problems, children's shoes are welcome to enthusiastically guide, thankful.




Posted by sprocket on Wed, 19 Jun 2019 19:20:59 -0700