androidservicebluetooth-lowenergycharacteristics

How can read all characteristic's value of my BLE device?


I'm building an app with Android Studio that can read the value from a device BLE. This device, have 4 services. The fourth services have 3 characteristic. I want to read the all characteristic of this fourth service.

This device, can send more information, so I want that the application can storage the all information that arrive from device BLE.

So this is my code:

@TargetApi(21)
public class BLEActivity extends BaseActivity {

    private BluetoothAdapter mBluetoothAdapter;
    private int REQUEST_ENABLE_BT = 1;
    private Handler mHandler;
    private static final long SCAN_PERIOD = 10000;
    private BluetoothLeScanner mLEScanner;
    private ScanSettings settings;
    private List<ScanFilter> filters;
    private BluetoothGatt mGatt;
    String mCurrentService;
    TextView tvBLE;
    ImageButton ibDownload;
    BluetoothDevice currDevice;
    private int id = 1000;
    public SensorDataAdapter adapter;
    final BLEActivity classe = this;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_ble);
        mHandler = new Handler();

        //mSensors = db.getAllSensorTypes();
        //BLUETOOTH LOW ENERGY NON SUPPORTATO
        if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
            Toast.makeText(this, "BLE Not Supported",
                    Toast.LENGTH_SHORT).show();
            finish();
        }
        final BluetoothManager bluetoothManager =
                (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = bluetoothManager.getAdapter();
        //VERIFICO SE IL BLUETOOTH DEL DISPOSITIVO E' ABILITATO
        //OPPURE NO. SE NON è ABILITATO DEVO CHIEDERE ALL'UTENTE DI ATTIVARLO
        // Ensures Bluetooth is available on the device and it is enabled. If not,
        if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
        }

        ibDownload.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(currDevice!=null){
                    mGatt = currDevice.connectGatt(getBaseContext(), false, gattCallback);
                    scanLeDevice(false);// will stop after first device detection
                }
            }
        });
    }

    private void scanLeDevice(final boolean enable) {
        if (enable) {
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (Build.VERSION.SDK_INT < 21) {
                        mBluetoothAdapter.stopLeScan(mLeScanCallback);
                    } else {
                        mLEScanner.stopScan(mScanCallback);

                    }
                }
            }, SCAN_PERIOD);
            if (Build.VERSION.SDK_INT < 21) {
                mBluetoothAdapter.startLeScan(mLeScanCallback);
            } else {
                mLEScanner.startScan(filters, settings, mScanCallback);
            }
        } else {
            if (Build.VERSION.SDK_INT < 21) {
                mBluetoothAdapter.stopLeScan(mLeScanCallback);
            } else {
                mLEScanner.stopScan(mScanCallback);
            }
        }
    }


    private ScanCallback mScanCallback = new ScanCallback() {
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            Log.i("callbackType", String.valueOf(callbackType));
            Log.i("result", result.toString());
            BluetoothDevice btDevice = result.getDevice();
            connectToDevice(btDevice);
        }

        @Override
        public void onBatchScanResults(List<ScanResult> results) {
            for (ScanResult sr : results) {
                Log.i("ScanResult - Results", sr.toString());
            }
        }

        @Override
        public void onScanFailed(int errorCode) {
            Log.e("Scan Failed", "Error Code: " + errorCode);
        }
    };

    private BluetoothAdapter.LeScanCallback mLeScanCallback =
            new BluetoothAdapter.LeScanCallback() {
                @Override
                public void onLeScan(final BluetoothDevice device, int rssi,
                                     byte[] scanRecord) {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Log.i("onLeScan", device.toString());
                            connectToDevice(device);
                        }
                    });
                }
            };

    public void connectToDevice(BluetoothDevice device) {
        if (mGatt == null) {
            currDevice = device;
            ibDownload.setEnabled(true);
            ibDownload.setImageResource(R.drawable.download_ok);
        }
    }

    private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            Log.i("onConnectionStateChange", "Status: " + status);
            switch (newState) {
                case BluetoothProfile.STATE_CONNECTED:
                    Log.i("gattCallback", "STATE_CONNECTED");
                    gatt.discoverServices();
                    break;
                case BluetoothProfile.STATE_DISCONNECTED:
                    Log.e("gattCallback", "STATE_DISCONNECTED");
                    break;
                default:
                    Log.e("gattCallback", "STATE_OTHER");
            }
        }

     @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            List<BluetoothGattService> services = gatt.getServices();
            Log.i("onServicesDiscovered", services.toString());
            ;
            for(BluetoothGattService srv : services){
               // if(srv.getUuid().toString().equals(mSensors.get(1).getServUid())){
                    mCurrentService = srv.getUuid().toString();
                    //RECUPERO SOLO IL SERVIZIO CON UID 1130
                if(mCurrentService.contains("1130")){
                    List<BluetoothGattCharacteristic> mListCars = srv.getCharacteristics();
                    //leggo le caratteristiche del servizio che cerco
                    for(BluetoothGattCharacteristic bc : mListCars){
                        //recupero solo le caratteristiche 1131, 1132
                        if(bc.getUuid().toString().contains("1131") ||
                                bc.getUuid().toString().contains("1132")){
                            //LEGGO LE 2 CARATTERISTICHE NECESSARIE
                           gatt.readCharacteristic(srv.getCharacteristic(bc.getUuid()));
                        }

                    }
                }else{
                    Log.i("SERVIZIO NON CORRETTO", "SERVIZIO NON CORRETTO");
                }

              //  }
            }


        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt,
                                         BluetoothGattCharacteristic
                                                 characteristic, int status) {
            Log.i("onCharacteristicRead", characteristic.toString());

               SensorData mSenData = new SensorData();
                    mSenData.setValue(characteristic.getStringValue(0));
                    Log.i("LETTURA DATI ", mSenData.getValue());
                    mSenData.setIdType(++id);
                    mSenData.setCharacteristic(characteristic.getUuid().toString());
                    mSenData.setValueTimestamp(db.getDateTime());
                    db.insertSensorData(mSenData);


        }




    };
}

with this code, I can read one the first characteristic of my service and only one value of the first characteristic.

I want to read all value of all characteristic automatically of my BLE device. How can I change my code to do this ?


Solution

  • You can achive multiple reads with the following code: First create a List

    private int ReadQueueIndex;
    private List<BluetoothGattCharacteristic> ReadQueue;
    

    In onServicesDiscovered add characteristics in ReadQueue:

    ReadQueue = new ArrayList<>();
    ReadQueue.add(characteristicsList.get(2));        
    ReadQueue.add(characteristicsList.get(1));            
    ReadQueue.add(characteristicsList.get(0));
    ReadQueueIndex = 2;
    ReadCharacteristics(ReadQueueIndex);
    

    Create ReadCharacteristics method

    private void ReadCharacteristics(int index){
       bluetoothGatt.readCharacteristic(ReadQueue.get(index));
    }
    

    Then in your onCharacteristicRead callback:

    String value =  Arrays.toString(characteristic.getValue());
    if(characteristic.getUuid().equals(characteristicsList.get(0).getUuid())){
      Log.i("Characteristic 0:", value);
    } else if(characteristic.getUuid().equals(characteristicsList.get(1).getUuid())){
      Log.i("Characteristic 1:", value);
    } else if(characteristic.getUuid().equals(characteristicsList.get(2).getUuid())){
      Log.i("Characteristic 2:", value);
    }
    ReadQueue.remove(ReadQueue.get(ReadQueueIndex));
    if (ReadQueue.size() >= 0) {
        ReadQueueIndex--;
        if (ReadQueueIndex == -1) {
           Log.i("Read Queue: ", "Complete");
        }
        else {
           ReadCharacteristics(ReadQueueIndex);
        }
     }
    

    Hope its helpful.