I can't figure out how to get the 'onReadRemoteRssi' callback work.
My code is very simple :
final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
BluetoothAdapter mBluetoothAdapter = bluetoothManager.getAdapter();
BluetoothGatt gatt;
mBluetoothAdapter.startLeScan(new LeScanCallback() {
#Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] record) {
gatt = device.connectGatt(getApplicationContext(), false, new BluetoothGattCallback() {
#Override
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
super.onReadRemoteRssi(gatt, rssi, status);
Log.d(TAG, "rssi is : " + rssi);
}
});
}
});
gatt.readRemoteRssi(); //returns true
The callback is never called.
Does anyone have any idea ?
Thanks !
Put readRemoteRssi() in the callback onConnectionStateChange() of BluetoothGattCallback.
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
String intentAction;
if (newState == BluetoothProfile.STATE_CONNECTED) {
intentAction = ACTION_GATT_CONNECTED;
mConnectionState = STATE_CONNECTED;
boolean rssiStatus = mBluetoothGatt.readRemoteRssi();
broadcastUpdate(intentAction);
// Attempts to discover services after successful connection.
Log.i(TAG, "Attempting to start service discovery:" +
mBluetoothGatt.discoverServices());
}
}
};
And also put the onReadRemoteRssi in BluetoothGattCallback function
#Override
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status){
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.d(TAG, String.format("BluetoothGatt ReadRssi[%d]", rssi));
}
}
http://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#readRemoteRssi()
Async call to start reading signal strength.
http://developer.android.com/reference/android/bluetooth/BluetoothGattCallback.html#onReadRemoteRssi(android.bluetooth.BluetoothGatt,%20int,%20int)
Callback after the read finishes.
Need to connect before read
reference here
Continual Bluetooth LE Signal Strength on Android
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(deviceAddress);
BluetoothGatt bluetoothGatt = getBluetoothGatt(device);
if (bluetoothGatt == null) {
return false;
}
boolean rdRemoteRssi = bluetoothGatt.readRemoteRssi();
Log.d(FTAG, "BluetoothGatt readRemoteRssi : " + rdRemoteRssi);
return true;
It will call onReadRemoteRssi call back.Need to connect before call this API.
Related
For some reason device does not transmit data (heart rate) over BLE. It connects fine, phone app is also able to discover services and connect to service.
I started up with iOS and Health app and actually saw some data coming through, so, it worked initially. Later, created the base for the BLE connectivity on Android app, it connected just fine, discovered the correct services and connected to these. And no data. Re-checked with iOS, also silence. Assuming that it is device'd problem (faulty sensors etc), took it to the shop I purchased it from. Tested it, worked like a charm with ANT+. So, it has to be BLE issue. The code itself is pretty much sample code from Android dev guides.
{
//0x180D - heart rate service
//0x2A37 - heart rate characteristic
private static HrmHandler instance;
private static UUID UUID_HRM_SERVICE = UUID.fromString("0000180d-0000-1000-8000-00805f9b34fb");
private static UUID UUID_HRM_CHARACTERISTIC = UUID.fromString("00002a37-0000-1000-8000-00805f9b34fb");
private static String LOG_TAG = HrmHandler.class.getSimpleName();
private BluetoothAdapter mBtAdapter;
private BluetoothDevice mBtDevice;
private String mBtDeviceAddress;
private Context mContext;
public static HrmHandler getInstance() {
if (instance == null)
instance = new HrmHandler();
return instance;
}
public void connect(Context ctx) {
mContext = ctx;
BluetoothManager bt_manager = (BluetoothManager) ctx.getSystemService(Context.BLUETOOTH_SERVICE);
mBtAdapter = bt_manager.getAdapter();
if (mBtAdapter == null || !mBtAdapter.isEnabled()) return;
mBtAdapter.startLeScan(new UUID[] {UUID_HRM_SERVICE}, this);
}
public void disconnect() {
}
#Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
Log.v(LOG_TAG, "Found HRM device " + device.getName());
mBtDevice = device;
mBtAdapter.stopLeScan(this);
mBtDeviceAddress = mBtDevice.getAddress();
mBtDevice.connectGatt(mContext, false,this);
}
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
Log.v(LOG_TAG, String.format("Connection state change, new state %d", newState));
if (mBtDeviceAddress == null || !mBtDeviceAddress.equals(gatt.getDevice().getAddress()))
return; //we are not interested about that connection state
if (newState == BluetoothProfile.STATE_CONNECTED) {
Log.v(LOG_TAG, "Device connected");
gatt.discoverServices();
return;
}
if (newState == BluetoothProfile.STATE_DISCONNECTED) {
Log.v(LOG_TAG, "Device disconnected");
return;
}
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (gatt != null) {
BluetoothGattCharacteristic characteristic = null;
List<BluetoothGattService> services = gatt.getServices();
for (BluetoothGattService s : services) {
Log.v(LOG_TAG, String.format("Discovered %s, uuid %s", s.toString(), s.getUuid().toString()));
}
BluetoothGattService service = gatt.getService(UUID_HRM_SERVICE);
if (service != null)
characteristic = service.getCharacteristic(UUID_HRM_CHARACTERISTIC);
gatt.readCharacteristic(characteristic);
gatt.setCharacteristicNotification(characteristic, true);
}
}
#Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
if (!UUID_HRM_CHARACTERISTIC.equals(characteristic.getUuid())) {
Log.v(LOG_TAG, "READ: Not interesting characteristic " + characteristic.getUuid().toString());
return;
}
int flags = characteristic.getProperties();
int format = (flags & 0x01) != 0 ? BluetoothGattCharacteristic.FORMAT_UINT16 : BluetoothGattCharacteristic.FORMAT_UINT8;
int heart_rate = characteristic.getIntValue(format, 1);
Log.v(LOG_TAG, String.format("Heart rate %d bpm", heart_rate) );
}
#Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
if (!UUID_HRM_CHARACTERISTIC.equals(characteristic.getUuid())) {
Log.v(LOG_TAG, "CHANGED: Not interesting characteristic " + characteristic.getUuid().toString());
return;
}
gatt.readCharacteristic(characteristic);
}
Can anyone help me forward, especially someone at Garmin, or is it common and known issue and I just should forget about it and try to go forward with ANT+?
I am following this tutorial. https://medium.com/#avigezerit/bluetooth-low-energy-on-android-22bc7310387a
Trying to understand LeScancallBacks
I am also following the documentation and the sample for Bluetooth devices from google
BluetoothAdapter.LeScanCallback scanCallback =
new BluetoothAdapter.LeScanCallback() {};
bluetoothAdapter.startLeScan(scanCallback);
#Override
public void onLeScan(final BluetoothDevice device, int rssi,
byte[] scanRecord) {
if(device.address == HR_SENSOR_ADDRESS){
myDevice = device;
}
}
My Code gives me the following error:
"Class 'Anonymous class derived from LeScanCallback' must either be
declared abstract or implement abstract method
'onLeScan(BluetoothDevice, int, byte[])' in 'LeScanCallback'"
When I compare it with the code from google.
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
String intentAction;
if (newState == BluetoothProfile.STATE_CONNECTED) {
intentAction = ACTION_GATT_CONNECTED;
mConnectionState = STATE_CONNECTED;
broadcastUpdate(intentAction);
Log.i(TAG, "Connected to GATT server.");
// Attempts to discover services after successful connection.
Log.i(TAG, "Attempting to start service discovery:" +
mBluetoothGatt.discoverServices());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
intentAction = ACTION_GATT_DISCONNECTED;
mConnectionState = STATE_DISCONNECTED;
Log.i(TAG, "Disconnected from GATT server.");
broadcastUpdate(intentAction);
}
}
This is the only other Callback I can find, is it possible that someone can help? I tried to program this project, alone for some time.
When you define that scanCallback object, you need to add in the required method like so:
BluetoothAdapter.LeScanCallback scanCallback = new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
//do stuff here
}
};
You can then handle the response in that onLeScan method.
In Java, an abstract class requires that any instantiation of it must implement the required methods, which is the error you were getting.
I'm trying to read the heart rate from a BLE device (It's a smartwatch and the model is CURREN R5 Pro), but when I get the Heart Rate Service, it returns null.
This is the code:
class Constants {
final static UUID HEART_RATE_SERVICE_UUID = convertFromInteger(0x180D);
final static UUID HEART_RATE_MEASUREMENT_UUID = convertFromInteger(0x2A37);
final static UUID HEART_RATE_CONTROL_POINT_UUID = convertFromInteger(0x2A39);
final static UUID CLIENT_CHARACTERISTIC_CONFIG_UUID = convertFromInteger(0x2902);
private static UUID convertFromInteger(int i) {
final long MSB = 0x0000000000001000L;
final long LSB = 0x800000805f9b34fbL;
long value = i & 0xFFFFFFFF;
return new UUID(MSB | (value << 32), LSB);
}
}
private final BluetoothGattCallback bluetoothGattCallback = new BluetoothGattCallback() {
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
bluetoothGatt.discoverServices();
Log.d(TAG, "Connected");
}
if (newState == BluetoothProfile.STATE_DISCONNECTED) {
Log.d(TAG, "Disconnected");
}
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
//getCharacteristic(HEART_RATE_MEASUREMENT_UUID) returns null
BluetoothGattCharacteristic characteristic = gatt.getService(HEART_RATE_SERVICE_UUID)
.getCharacteristic(HEART_RATE_MEASUREMENT_UUID);
gatt.setCharacteristicNotification(characteristic, true);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CLIENT_CHARACTERISTIC_CONFIG_UUID);
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
gatt.writeDescriptor(descriptor);
}
}
#Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
BluetoothGattCharacteristic characteristic = gatt.getService(HEART_RATE_SERVICE_UUID)
.getCharacteristic(HEART_RATE_CONTROL_POINT_UUID);
characteristic.setValue(DATA_STREAMING_COMMAND);
gatt.writeCharacteristic(characteristic);
}
#Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
if (HEART_RATE_MEASUREMENT_UUID.equals(characteristic.getUuid())) {
Log.d(TAG, "HEART_RATE_MEASUREMENT_UUID");
//PROCESS DATA
}
if (HEART_RATE_CONTROL_POINT_UUID.equals(characteristic.getUuid())) {
Log.d(TAG, "HEART_RATE_CONTROL_POINT_UUID");
//PROCESS DATA
}
}
};
However, the only app that is able to read the heart rate from the device is Wearfit. Other applications are not able to read the heart rate from this device.
The services that I'm able to get are these:
00001800-0000-1000-8000-00805f9b34fb
00001801-0000-1000-8000-00805f9b34fb
6e400001-b5a3-f393-e0a9-e50e24dcca9e
00001530-1212-efde-1523-785feabcd123
0000fee7-0000-1000-8000-00805f9b34fb
Has anyone experienced this situation? Is there anything wrong with my code? Thanks for your help.
I'm trying to read GATT characteristic values from a Bluetooth LE device (a Heart Rate bracelet). Its specs are:
Services
Characteristics
I have not yet figured out how to "read" the specifications and "translate" them into code.
I need to show on my app the heartbeats detected by the device. What is the way to read the GATT values? A code example would be much appreciated :)
Follow my actual source code.
SETUP THE BLUETOOT CONNECTION
private BluetoothAdapter mBluetoothAdapter;
private BluetoothGatt mBluetoothGatt;
private Handler mHandler;
private static final int REQUEST_ENABLE_BT = 1;
private static final long SCAN_PERIOD = 10000;
// ...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bluetooth);
mHandler = new Handler();
// BLE is supported?
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, "Bluetooth Low Energy non supportato", Toast.LENGTH_SHORT).show();
finish();
}
final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
// Bluetooth is supported?
if (mBluetoothAdapter == null) {
Toast.makeText(this, "Bluetooth non supportato", Toast.LENGTH_SHORT).show();
finish();
}
}
#Override
protected void onResume() {
super.onResume();
// Bluetooth is enabled?
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
scanLeDevice(true);
}
#Override
protected void onPause() {
super.onPause();
if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) {
scanLeDevice(false);
}
}
DISCOVER BLE DEVICES AND CONNECT WITH HEART RATE MONITOR
// Device scan callback.
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(TAG, "Name: " + device.getName() + " (" + device.getAddress() + ")");
String deviceAddress = device.getAddress();
if (deviceAddress.equals("C0:19:37:54:9F:30")) {
connectToDevice(device);
}
}
});
}
};
public void connectToDevice(BluetoothDevice device) {
if (mBluetoothGatt == null) {
Log.i(TAG, "Attempting to connect to device " + device.getName() + " (" + device.getAddress() + ")");
mBluetoothGatt = device.connectGatt(this, true, gattCallback);
scanLeDevice(false);// will stop after first device detection
}
}
private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
Log.i(TAG, "Status: " + status);
switch (newState) {
case BluetoothProfile.STATE_CONNECTED:
Log.i(TAG, "STATE_CONNECTED");
//BluetoothDevice device = gatt.getDevice(); // Get device
gatt.discoverServices();
break;
case BluetoothProfile.STATE_DISCONNECTED:
Log.e(TAG, "STATE_DISCONNECTED");
break;
default:
Log.e(TAG, "STATE_OTHER");
}
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
List<BluetoothGattService> services = gatt.getServices();
Log.i(TAG, "Services: " + services.toString());
BluetoothGattCharacteristic bpm = services.get(2).getCharacteristics().get(0);
gatt.readCharacteristic(services.get(0).getCharacteristics().get(0));
}
#Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
// my attempt to read and print characteristics
byte[] charValue = characteristic.getValue();
byte flag = charValue[0];
Log.i(TAG, "Characteristic: " + flag);
//gatt.disconnect();
}
};
try with this inside gattCallback:
#Override
public synchronized void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
final byte[] dataInput = characteristic.getValue();
}
EDIT
And I think you are going to receive a byte with the hear rate data, use this function to get the int value:
public int unsignedByteToInt(byte b) {
return b & 0xFF;
}
And call it inside onCharacteristicChanged():
final byte[] dataInput = characteristic.getValue();
int hearRate = unsignedByteToInt(dataInput);
EDIT 2
Create a notification listener for the heart rate:
public void setHeartRateNotification(boolean enable){
String uuidHRCharacteristic = "YOUR CHARACTERISTIC";
BluetoothGattService mBluetoothLeService = null;
BluetoothGattCharacteristic mBluetoothGattCharacteristic = null;
for (BluetoothGattService service : mBluetoothGatt.getServices()) {
if ((service == null) || (service.getUuid() == null)) {
continue;
}
if (uuidAccelService.equalsIgnoreCase(service.getUuid().toString())) {
mBluetoothLeService = service;
}
}
if(mBluetoothLeService!=null) {
mBluetoothGattCharacteristic =
mBluetoothLeService.getCharacteristic(UUID.fromString(uuidHRCharacteristic));
}
else{
Log.i("Test","mBluetoothLeService is null");
}
if(mBluetoothGattCharacteristic!=null) {
setCharacteristicNotification(mBluetoothGattCharacteristic, enable);
Log.i("Test","setCharacteristicNotification:"+true);
}
else{
Log.i("Test","mBluetoothGattCharacteristic is null");
}
}
And set it onServiceDiscover inside gattCallback:
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
Log.i("Test", "onServicesDiscovered received: " + status);
setHeartRateNotification(true);
}
Although similar questions have been asked but it's slightly different. I know how to pass data to a connected BLE device but I think I'm doing something wrong for which I need help.
The code below contains all the methods from my class that is extending BroadcastReceiver.
I scan and connect to a device specified by `PEN_ADDRESS`.
In `onServicesDiscovered` method I look for a service whose `UUID` contains `abcd`.
Then I loop through the characteristics of this services and look for three characteristics with specific strings in their `UUID`.
The third characteristic is a writable characteristic in which I'm trying to write data by calling the method `writeCharac(mGatt,writeChar1,123);`
The data `123` passed above is just a dummy data.
I debugged my code while trying writing to this characteristic but on putting breakpoints inside the writeCharac method, I found that the status value is false, indicating that the write was not successful.
Am I missing something here? Please do help!
public class BackgroundReceiverFire extends BroadcastReceiver {
Context context;
private BluetoothAdapter mBluetoothAdapter;
private BluetoothGatt mGatt;
private BluetoothLeService mBluetoothLeService;
private boolean mScanning;
private final String TAG = "READING: ";
private BluetoothDevice mDevice;
private Handler mHandler;
private static final int REQUEST_ENABLE_BT = 1;
private final String PEN_ADDRESS = "FB:23:AF:42:5C:56";
// Stops scanning after 10 seconds.
private static final long SCAN_PERIOD = 10000;
public void onReceive(Context context, Intent intent) {
this.context = context;
Toast.makeText(context, "Started Scanning", LENGTH_SHORT).show();
initializeBluetooth();
startScan();
}
private void initializeBluetooth() {
mHandler = new Handler();
// Use this check to determine whether BLE is supported on the device. Then you can
// selectively disable BLE-related features.
// Initializes a Bluetooth adapter. For API level 18 and above, get a reference to
// BluetoothAdapter through BluetoothManager.
final BluetoothManager bluetoothManager =
(BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
// Checks if Bluetooth is supported on the device.
if (mBluetoothAdapter == null) {
Toast.makeText(this.context, "No Bluetooth", LENGTH_SHORT).show();
return;
}
}
private void startScan() {
scanLeDevice(true);
}
private void stopScan() {
scanLeDevice(false);
}
private void scanLeDevice(final boolean enable) {
if (enable) {
// Stops scanning after a pre-defined scan period.
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
}, SCAN_PERIOD);
mScanning = true;
//Scanning for the device
mBluetoothAdapter.startLeScan(mLeScanCallback);
} else {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
}
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
if (device.getAddress().matches(PEN_ADDRESS)) {
connectBluetooth(device);
Toast.makeText(context, "Device Found: " + device.getAddress(), Toast.LENGTH_LONG).show();
}
}
};
private void connectBluetooth(BluetoothDevice insulinPen) {
if (mGatt == null) {
Log.d("connectToDevice", "connecting to device: " + insulinPen.toString());
mDevice = insulinPen;
mGatt = insulinPen.connectGatt(context, true, gattCallback);
scanLeDevice(false);// will stop after first device detection
}
}
private void enableBluetooth() {
if (!mBluetoothAdapter.isEnabled()) {
mBluetoothAdapter.enable();
}
scanLeDevice(true);
}
private void disableBluetooth() {
if (mBluetoothAdapter.isEnabled()) {
mBluetoothAdapter.disable();
}
}
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:
gatt.discoverServices();
break;
case BluetoothProfile.STATE_DISCONNECTED:
Log.e("gattCallback", "STATE_DISCONNECTED");
Log.i("gattCallback", "reconnecting...");
BluetoothDevice mDevice = gatt.getDevice();
mGatt = null;
connectBluetooth(mDevice);
break;
default:
Log.e("gattCallback", "STATE_OTHER");
break;
}
}
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
mGatt = gatt;
List<BluetoothGattService> services = mGatt.getServices();
Log.i("onServicesDiscovered", services.toString());
Iterator<BluetoothGattService> serviceIterator = services.iterator();
while(serviceIterator.hasNext()){
BluetoothGattService bleService = serviceIterator.next();
if(bleService.getUuid().toString().contains("abcd")){
//Toast.makeText(context,"Got the service",Toast.LENGTH_SHORT);
BluetoothGattCharacteristic readChar1 = bleService.getCharacteristics().get(0);
for (BluetoothGattDescriptor descriptor : readChar1.getDescriptors()) {
descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
mGatt.writeDescriptor(descriptor);
mGatt.setCharacteristicNotification(readChar1, true);
}
//mGatt.readCharacteristic(readChar1);
BluetoothGattCharacteristic readChar2 = bleService.getCharacteristics().get(1);
for (BluetoothGattDescriptor descriptor : readChar2.getDescriptors()) {
descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
mGatt.writeDescriptor(descriptor);
mGatt.setCharacteristicNotification(readChar2, true);
}
//mGatt.readCharacteristic(readChar2);
BluetoothGattCharacteristic writeChar1 = bleService.getCharacteristics().get(2);
for (BluetoothGattDescriptor descriptor : writeChar1.getDescriptors()) {
descriptor.setValue( BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
mGatt.writeDescriptor(descriptor);
mGatt.setCharacteristicNotification(writeChar1, true);
}
writeCharac(mGatt,writeChar1,123);
}
}
//gatt.readCharacteristic(therm_char);
}
public void writeCharac(BluetoothGatt gatt, BluetoothGattCharacteristic charac, int value ){
if (mBluetoothAdapter == null || gatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
/*
BluetoothGattCharacteristic charac = gattService
.getCharacteristic(uuid);
*/
if (charac == null) {
Log.e(TAG, "char not found!");
}
int unixTime = value;
String unixTimeString = Integer.toHexString(unixTime);
byte[] byteArray = hexStringToByteArray(unixTimeString);
charac.setValue(byteArray);
boolean status = mGatt.writeCharacteristic(charac);
if(status){
Toast.makeText(context,"Written Successfully",Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(context,"Error writing characteristic",Toast.LENGTH_SHORT).show();
}
}
public byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len/2];
for(int i = 0; i < len; i+=2){
data[i/2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i+1), 16));
}
return data;
}
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic
characteristic, int status) {
Log.i("onCharacteristicRead", characteristic.toString());
String characteristicValue = characteristic.getValue().toString();
Log.d("CHARACTERISTIC VALUE: ", characteristicValue);
gatt.disconnect();
}
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic
characteristic) {
String value = characteristic.getValue().toString();
Log.d(TAG,value);
}
};
Although the BLE API is asynchronous in nature, the actual signal transmission is inevitably synchronous. You have to wait for the previous connect/write/read call to callback before starting any connecting/writing/reading operation.
In your code onServicesDiscovered(BluetoothGatt gatt, int status) function, you called mGatt.writeDescriptor(descriptor) twice before trying to write the characteristic. The API will refuse to start your write request as it is being busy writing the descriptor, and return false for your mGatt.writeCharacteristic(charac) call.
So just wait for the writeDescriptor to callback before calling writeCharacteristic. This nature is not well documented but you can find some source here and here.
Thanks #reTs and #pooja for suggestions. The issue was due to these two lines
mGatt = nullconnectBluetooth(mDevice);
in STATE_DISCONNECTED. I had figured it out but don't remember the exact reason. Posting it just in case it is helpful.