Deep Understanding of Android Bluetooth --"Advanced Chapter"

Keywords: Android Mobile Attribute SDK

In Deeply Understanding Android Bluetooth --"Basic Chapter" In one article, we have an understanding of each version of Bluetooth, the course of Bluetooth version and its advantages and disadvantages. Then let's go a little deeper and continue driving into the BLE chapter.

Bluetooth BLE4.x

BLE is divided into three parts:

  • Service
  • Characteristic
  • Descriptor

    All three parts use UUID as the unique identifier. UUID is in this format: 0000ffe1-0000-1000-8000-00805f9b34fb. For example, with three services, there are three different UUIDs that correspond to services. These UUIDs are written in hardware and can be read through the API provided by BLE.

  • A BLE terminal can contain multiple services, a Service can contain multiple Characteristic, a Characteristic can contain one value and multiple Descriptors, and a Descriptor can contain one Value. Characteristic is very important. It is the key to exchange data between mobile phone and BLE terminal. Reading and setting data are all related attributes of Characteristic.

Introduction to API

  • 1. Let's introduce some nouns about Bluetooth 4.0.
    (1)GATT(Gneric Attibute Profile)

    Through the ble connection, read and write attribute class small data Profile universal specification. Now all ble application Profiles are based on GATT

    • (2)ATT(Attribute Protocal) GATT is based on ATT Potocal, which is specially designed for BLE devices. It uses as little data as possible in the transmission process. Each attribute has a unique UUID, chartcteristics and Service.
    • (3)Service is a collection of Characteristic.
    • (4) Characteristic type.

    For example. There's a Bluetooth ble manometer. He may include multiple services, each of which includes multiple Characteristic services.

    Note: Bluetooth can only support SDK >= 18 for systems with Android 4.3 or more.

  • 2. Following are the steps of development:

  • 2.1 Get Bluetooth Manager first

  • 2.2 Get Bluetooth Adapter
  • 2.3 Create Bluetooth Adapter. LeScan Callback
  • 2.4. Start searching for devices.
  • 2.5. Bluetooth Device describes a Bluetooth device that provides the Mac address of getAddress() device and the name of getName() device.
  • 2.6 Start Connecting Equipment
  • 2.7 Get the service of the device and the corresponding Characteristic of the service after connecting to the device.
  • 2.8 After acquiring the feature, find the feature in the service that can write instructions to the downstream machine and write instructions to the feature.
  • 2.9 After successful writing, start reading the data returned by the device.
  • 2.10. Disconnect
  • 2.11. Data Conversion Method
Perhaps the whole is the above steps. But it is also the process of communication according to the agreement of the manufacturer.

So how to use it? We need to drive down.

1. Adding permissions

Like classical Bluetooth, applications using Bluetooth need to declare BLUETOOTH privileges. If they need to scan devices or operate Bluetooth settings, they also need BLUETOOTH_ADMIN privileges:

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

In addition to Bluetooth privileges, you also need to declare uses-feature s if you need BLE feature s:

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

When required is true on time, the application can only be installed and run on BLE-enabled Android devices. When required is false, Android devices can be installed and run normally. It is necessary to determine whether the device supports BLE feature s at code runtime:

// Use this check to determine whether BLE is supported on the device. Then
// you can selectively disable BLE-related features.
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
    Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
    finish();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

Step 1: Turn on Bluetooth:

  • 1. First, there are two ways to get Bluetooth Adapter:
private BluetoothManager bluetoothManager;

bluetoothManager =   (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
  • 1
  • 2
  • 3
  • 4

Or:

mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
  • 1

Both lines are acceptable.

Note: Here we get Bluetooth Manager through getSystem Service, and Bluetooth Adapter through Bluetooth Manager. Bluetooth Manager supports Android 4.3 and above (API level 18).  
- 2. Judging whether mobile devices have Bluetooth modules

  // Check if Bluetooth is supported on the device
        if (mBluetoothAdapter == null) {
            showToast("Bluetooth module not found");
            return;
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 3. Turn on Bluetooth

    There are two ways to turn on Bluetooth devices:

    • The first kind of direct simple violence does not prompt users:
    if (!mBluetoothAdapter.isEnabled()) {
                mBluetoothAdapter.enable();
    }
    • 1
    • 2
    • 3
    • The second kind of straight and elegant practice opens with a bullet-box to prompt, implicitly starting Intent:
    if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
        Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
    }
    • 1
    • 2
    • 3
    • 4
  • 4. Scanning Bluetooth Devices

    Here I put the BLE address scanned into the List collection. Here we can write a way to encapsulate it.

    /***********
     * Scanning equipment
     ********/
    private void scanLeDevice(final boolean enable) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
            if (enable) {
                devices.clear();//Empty collection
                // Stops scanning after a pre-defined scan period.
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
                            mBluetoothAdapter.stopLeScan(mLeScanCallback);
                        }
                    }
                }, INTERVAL_TIME);
                mBluetoothAdapter.startLeScan(mLeScanCallback);
            } else {
                try {
                    mBluetoothAdapter.stopLeScan(mLeScanCallback);
                } catch (Exception e) {
                }
            }
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

In this scanning method, we can see in Android Studio or Eclipse that the startLeScan method has a horizontal line indicating that this method displays expired methods. So

If you only need to search for the specified UUID peripherals, you can call the startLeScan(UUID[], BluetoothAdapter.LeScanCallback) method.  
The UUID array specifies the UUID of GATT Services supported by your application.

The initial code for LeScan Callback is as follows:

private void initCallBack(){
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
            mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
                @Override
                public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            if (device != null) {
                                if (!TextUtils.isEmpty(device.getName())) {
                                   // devices.add(device);
                                    String name = device.getName();
                                    if (name.contains(BluetoothDeviceAttr.OYGEN_DEVICE_NAME)) {
                                        if (!devices.contains(device)) {
                                            devices.add(device);
                                        }
                                    }
                                }
                            }
                        }
                    });
                }
            };
        } else {
            getToast("Bluetooth version of device is too low");
            return;
        }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

Well, if there are many devices, we'll talk about finding a lot of devices. We can choose the address we need to link to. However, it should be noted that when searching, you can only search for traditional Bluetooth devices or BLE devices, which are completely independent and cannot be searched at the same time.

  • 5. Linking devices
 final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
        if (device == null) {
            Log.w(TAG, "Device not found.  Unable to connect.");
            return false;
        }
        // We want to directly connect to the device, so we are setting the autoConnect
        // parameter to false.
        mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

The connectGatt method of device is called here.

  /**
     * Connect to GATT Server hosted by this device. Caller acts as GATT client.
     * The callback is used to deliver results to Caller, such as connection status as well
     * as any further GATT client operations.
     * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
     * GATT client operations.
     * @param callback GATT callback handler that will receive asynchronous callbacks.
     * @param autoConnect Whether to directly connect to the remote device (false)
     *                    or to automatically connect as soon as the remote
     *                    device becomes available (true).
     * @throws IllegalArgumentException if callback is null
     */
    public BluetoothGatt connectGatt(Context context, boolean autoConnect,
                                     BluetoothGattCallback callback) {
        return (connectGatt(context, autoConnect,callback, TRANSPORT_AUTO));
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

The first parameter described in the api is the context object Context, the second parameter is whether to connect automatically, and the third parameter is the GattCallback callback of Bluetooth.

private BluetoothGattCallback GattCallback = new BluetoothGattCallback() {
    // Here are nine ways to do that, depending on what you want to do, and using those to do that.
    //When the connection state changes
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState){

    };
    //Result of callback response feature write operation.
    @Override
    public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status){

    };
    //Result of callback response feature reading operation.
    @Override
    public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
    }
    //Result of callback when service is found
    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
    }
    //When the connection can be read
    @Override
   public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {

            super.onDescriptorRead(gatt, descriptor, status);
      }  
    ......
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

The process of connection is either through service or in activity.  
Okay, so far, the whole process of a BLE Bluetooth connection device is clear.

Android 4.x Bluetooth is not mature enough

But in the actual operation process, there will inevitably be some pitfalls. For example, when I use an address to connect a Bluetooth device, occasionally there will be problems such as Bluetooth can't connect or not returning data after connecting to the device. At this point, we may reboot Bluetooth or mobile phone and immediately succeed. At this time, we must not deceive, nor doubt our own life. This is because Android 4.x Bluetooth is still not mature. At present, it is a testing phase.  
* Mobile phones may not be able to search for Bluetooth devices.
* Sometimes data is not received on the radio.
* If something goes wrong, you need to restart the phone or restart it to get back to normal.

What shall we do at this time?

Don't complain at this time, is it hard for us as Android programmers to be doomed to be so hard?

The answer is No.

How to optimize it? Then we should operate from UI interface and user experience.
* Make a timer. If the Bluetooth device is turned on and exists, you can restart Bluetooth when the Bluetooth device is not found within 5 seconds of mobile phone search, and search again after receiving Bluetooth on the radio.
* Users can be prompted on the UI.
- When Bluetooth is booted, prompt the user to turn on Bluetooth.
- When Bluetooth is on, when it is on, it prompts the user that Bluetooth is on.  
- Bluetooth is on and the device is not connected, prompting the user to connect.
- The device is connecting to the mobile phone, prompting the user that it is connecting, please wait.  
- Bluetooth device connected to the mobile phone, is reading, prompting the data is reading.

We can't do anything on Android, we can do what we can in experience.

BLE Device Requirements for Bluetooth Connection of Mobile Phone

  • System SDK >= 18 for Android 4.3 or above
  • Bluetooth Version >= 4.0

Learning Reference demo Download Address:
https://github.com/androidstarjack/Bluetooth_4.3-master

Learned here, about the Android BLE Bluetooth connection, we have basically achieved Bluetooth search, connection, reading and so on.

If hardware such as bracelet, thermometer, sweat meter, electrocardiogram, sphygmomanometer and other Bluetooth devices are often involved in the project, blue-related knowledge will be used. Here I first step on the pit in advance for you, and summarized, for the small partners behind in the study of Bluetooth as little as possi ble to step on some pits. If you do not have a clear understanding of Bluetooth, please refer to the in-depth understanding. Android Bluetooth Bluetooth 4.0: Basic Chapter.

If you think this article is helpful to you, you are welcome to join QQ group: 232203809??
Wechat Public Number: Terminal R&D Department

Posted by tbone-tw on Fri, 12 Apr 2019 10:45:33 -0700