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 ?
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.