Need my app to connect to two BLE devices - android

I know it's been discussed on here before, but i never found a concrete demonstration on how this is achieved. So far I'm able to connect to one device, and this is what i have so far:
A MainActivity with no layout
public class MainActivity extends AppCompatActivity {
private Handler mHandler;
private BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
private static final int REQUEST_ENABLE_BT = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHandler = new Handler();
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice("E8:FF:34:49:A9:5B");
final Intent intent = new Intent(this, DeviceControlActivity.class);
intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_NAME, device.getName());
intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_ADDRESS, device.getAddress());
startActivity(intent);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// User chose not to enable Bluetooth.
if (requestCode == REQUEST_ENABLE_BT && resultCode == Activity.RESULT_CANCELED) {
finish();
return;
}
super.onActivityResult(requestCode, resultCode, data);
}
#Override
protected void onResume() {
super.onResume();
// Ensures Bluetooth is enabled on the device. If Bluetooth is not currently enabled,
// fire an intent to display a dialog asking the user to grant permission to enable it.
if (!mBluetoothAdapter.isEnabled()) {
if (!mBluetoothAdapter.isEnabled()) {
Toast.makeText(getApplicationContext(), "Enable Bluetooth in phone settings.",
Toast.LENGTH_LONG).show();
}
}
}
}
DeviceControlActivity with code to manage Service lifecycle.
private final ServiceConnection mServiceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName componentName, IBinder service) {
mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
if (!mBluetoothLeService.initialize()) {
Log.e(TAG, "Unable to initialize Bluetooth");
finish();
}
// Automatically connects to the device upon successful start-up initialization.
mBluetoothLeService.connect(mDeviceAddress);
}
#Override
public void onServiceDisconnected(ComponentName componentName) {
mBluetoothLeService = null;
}
};
Establish connection in onCreate
Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
Receiver to handle various events fired by the Service.
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
mConnected = true;
updateConnectionState(R.string.connected);
mConnectionState.setTextColor(Color.parseColor("#FF17AA00"));
invalidateOptionsMenu();
} else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
mConnected = false;
updateConnectionState(R.string.disconnected);
mConnectionState.setTextColor(Color.parseColor("#ff0000"));
invalidateOptionsMenu();
//clearUI();
} else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
// Show all the supported services and characteristics on the user interface.
//displayGattServices(mBluetoothLeService.getSupportedGattServices());
List<BluetoothGattService> servs = mBluetoothLeService.getSupportedGattServices();
for (int i = 0; servs.size() > i; i++) {
List<BluetoothGattCharacteristic> charac = servs.get(i).getCharacteristics();
for (int j = 0; charac.size() > i; i++) {
BluetoothGattCharacteristic ch = charac.get(i);
if (ch.getUuid() == chara) {
mBluetoothLeService.readCharacteristic(ch);
mBluetoothLeService.setCharacteristicNotification(ch, true);
}
}
}
} else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
displayData(intent.getStringExtra(BluetoothLeService.EXTRA_DATA));
}
}
};
After some research, i'm under the impression that i would have to edit the BluetoothGattCallback to be able to manage 2 connections. What i have so far:
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);
}
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
List<BluetoothGattService> services = gatt.getServices();
gatt.readCharacteristic(services.get(2).getCharacteristics().get
(0));
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
#Override
public void onCharacteristicRead(final BluetoothGatt gatt,final
BluetoothGattCharacteristic characteristic,
int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
new Thread(new Runnable() {
#Override
public void run() {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
gatt.readCharacteristic(characteristic);
}
}).start();
}
}
#Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
};

Related

Android BLE get connected but do not get any callback at BluetoothGattCallback()

I have an Arduino code driven ESP32 chip.
For Android code, it setup a callback for connection attempt
mGatt = device.connectGatt(this, false, gattCallback, TRANSPORT_LE );
but
private final BluetoothGattCallback gattCallback = new BluetoothGattCallback()
do not happen.
However, from Arduino side, it does see a connected happen and start to send data out. ESP32 also blink connected LED.
Any idea what was wrong?
SDK version is 26,
minSDK is 23,
targetSDK is 23,
run on Samsung Galaxy S7
thanks a lot!
#TargetApi(21)
public class MainActivity extends AppCompatActivity {
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;
private TextView line_1, line_2, line_3, line_4;
private ImageButton btnTrash, btnEmail;
private UUID uuid;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
uuid = UUID.fromString("8dc99748-0ad4-11e8-ba89-0ed5f89f718b");
line_1 = (TextView) findViewById(R.id.textLine1);
line_2 = (TextView) findViewById(R.id.textLine2);
line_3 = (TextView) findViewById(R.id.textLine3);
line_4 = (TextView) findViewById(R.id.textLine4);
mHandler = new Handler();
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();
}
private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
line_3.setText("" + status);
switch (newState) {
case BluetoothProfile.STATE_CONNECTED:
line_1.setText(" connected ");
Toast.makeText(getApplicationContext()," connected ", Toast.LENGTH_LONG);
// 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();
line_1.setText(" server discover");
gatt.readCharacteristic(services.get(1).getCharacteristics().get
(0));
}
#Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic
characteristic, int status) {
Log.i("onCharacteristicRead", characteristic.toString());
gatt.disconnect();
}
#Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic)
{
line_1.setText(" charactertics changed");
}
};
#Override
protected void onResume() {
super.onResume();
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
} else {
if (Build.VERSION.SDK_INT >= 21) {
mLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
settings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.build();
filters = new ArrayList<ScanFilter>();
}
scanLeDevice(true);
}
}
#Override
protected void onPause() {
super.onPause();
if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) {
scanLeDevice(false);
}
}
#Override
protected void onDestroy() {
if (mGatt == null) {
return;
}
mGatt.close();
mGatt = null;
super.onDestroy();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_ENABLE_BT) {
if (resultCode == Activity.RESULT_CANCELED) {
//Bluetooth not enabled.
finish();
return;
}
}
super.onActivityResult(requestCode, resultCode, data);
}
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);
// mLEScanner.startScan(filters, settings, mScanCallback);
}
}
}, SCAN_PERIOD);
if (Build.VERSION.SDK_INT < 21) {
mBluetoothAdapter.startLeScan(mLeScanCallback);
} else {
line_1.setText(" mLEScanner ");
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) {
super.onScanResult(callbackType, result);
BluetoothDevice btDevice = result.getDevice();
line_2.setText("try connect to " + btDevice.getName());
connectToDevice(btDevice);
}
#Override
public void onBatchScanResults(List<ScanResult> results) {
for (ScanResult sr : results) {
line_2.setText(" batch scan result");
}
}
#Override
public void onScanFailed(int errorCode) {
line_2.setText("scan fail");
}
};
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) {
try {
BluetoothSocket temp = device.createRfcommSocketToServiceRecord(uuid);
mGatt = device.connectGatt(this, false, gattCallback, TRANSPORT_LE );
} catch( Exception e)
{
}
line_3.setText( device.getAddress());
line_4.setText( "device type: "+ device.getType());
scanLeDevice(false);// will stop after first device detection
}
}
}

My Broadcast Receiver does not receive broadcasts from Local Service

I am new to android development and currently I am trying to modify the sample code for Bluetooth LE interfacing found here https://developer.android.com/samples/BluetoothLeGatt/index.html .
This demo project is divided into two activities but I want to reduce it to one activity; the DeviceControlActivity is changed into a 'regular' Java class.
After a few attempts I made the BluetoothLeService run with this constructor of my Device Control class:
public DeviceControl (BluetoothDevice device, Context context) {
mDeviceName = device.getName();
mDeviceAddress = device.getAddress();
this.context = context;
Log.d(TAG, "DeviceControl construktor");
Log.d(TAG, "Context = " + context);
Intent gattServiceIntent = new Intent(context, BluetoothLeService.class);
context.bindService(gattServiceIntent, mServiceConnection, context.BIND_AUTO_CREATE);
}
The BluetoothLeService class is ridden with Log.d()'s and seems to work fine; however, the broadcasts it emits here:
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);
}
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
#Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
}
#Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
};
private void broadcastUpdate(final String action) {
Log.d(TAG, "Methode broadcastUpdate aufgerufen. Action = " + action);
final Intent intent = new Intent(action);
sendBroadcast(intent);
}
However, they never arrive in the DeviceControl Class I originally bound the service to:
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Broadcast received");
final String action = intent.getAction();
if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
} else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
} else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
// Show all the supported services and characteristics on the user interface.
System.out.println("GATT-services discovered");
displayGattServices(mBluetoothLeService.getSupportedGattServices());
} else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
displayData(intent.getStringExtra(BluetoothLeService.EXTRA_DATA));
}
}
};
What's wrong here?
I cannot comment yet, but is it registered?
You have to register the broadcast receiver with the registerReceiver method.
P.S. If you are using the AppCompat library and do not need the broadcasts to leave your app, also look into the LocalBroadcastManager.
Thanks RobK,
Indeed I didn't register the broadcast. The code for registering wasn't in the onCreate() method in the sample project activity where I expectet everything necessary to set up the Service, but in the onResume() method.
Adding
registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
if (mBluetoothLeService != null) {
final boolean result = mBluetoothLeService.connect(mDeviceAddress);
Log.d(TAG, "Connect request result=" + result);
}
to the constructor and an additional custom intent filter
private static IntentFilter makeGattUpdateIntentFilter() {
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
return intentFilter;
}
solved it for me.

Android Bluetooth onCharacteristicChanged never called

I've followed the guide listed at https://developer.android.com/samples/BluetoothLeGatt/src/com.example.android.bluetoothlegatt/DeviceScanActivity.html
I can't figure out how to trigger a notify when the characteristic value changes. The method onCharacteristicChanged is never called but I know for a fact the value changes every 2 seconds. I am getting around this fact by calling readCharacteristic when I discover the service and then repeatedly afterwards. I don't believe this is the correct way rather I should only read when the onCharacteristicChanged method sends a broadcast. Is it possible to get notify to work or is this the best method?
Device Controller:
public class WarningActivity extends AppCompatActivity {
private static final String TAG = "WarningActivity Class";
private BluetoothLeService mBluetoothLeService;
public static WarningActivity wInstance;
private boolean mConnected = false;
private String mDeviceAddress;
private boolean quitService;
private TextView connectStatus;
private Button connectButton;
private Button cameraButton;
private BluetoothManager mBluetoothManager;
private Vibrator vib;
private Uri notification;
private Ringtone ring;
private final ServiceConnection mServiceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName componentName, IBinder service) {
mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
if (!mBluetoothLeService.initialize()) {
Log.e(TAG, "Unable to initialize Bluetooth");
finish();
}
mBluetoothLeService.connect(mDeviceAddress);
}
#Override
public void onServiceDisconnected(ComponentName componentName) {
mBluetoothLeService = null;
}
};
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
mConnected = true;
} else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
mConnected = false;
} else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
Log.i("Data: ", mBluetoothLeService.getSupportedGattService().toString());
BluetoothGattService mService = mBluetoothLeService.getSupportedGattService();
BluetoothGattCharacteristic characteristic = mService.getCharacteristic(mBluetoothLeService.ALERT_UUID);
mBluetoothLeService.setCharacteristicNotification(characteristic, true);
mBluetoothLeService.readCharacteristic(characteristic);
} else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
BluetoothGattService mService = mBluetoothLeService.getSupportedGattService();
BluetoothGattCharacteristic characteristic = mService.getCharacteristic(mBluetoothLeService.ALERT_UUID);
byte[] temp = intent.getByteArrayExtra(BluetoothLeService.EXTRA_DATA);
String tempString = Arrays.toString(temp);
Log.i("Data: ", Arrays.toString(temp));
mBluetoothLeService.readCharacteristic(characteristic);
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ColorDrawable colorDrawable = new ColorDrawable(Color.parseColor("#268011"));
getSupportActionBar().setBackgroundDrawable(colorDrawable);
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
connectButton = (Button) findViewById(R.id.connectButton);
connectButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.connected_logo, 0, 0);
connectButton.setClickable(false);
Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
Intent intent = getIntent();
mDeviceAddress = intent.getStringExtra("EXTRA_DEVICE_ADDRESS");
mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
vib = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
ring = RingtoneManager.getRingtone(getApplicationContext(), notification);
wInstance = this;
quitService = false;
connectStatus = (TextView) findViewById(R.id.connectMessage);
connectStatus.setText("Connected to: \n " + mDeviceAddress);
}
#Override
protected void onResume() {
super.onResume();
registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
if (mBluetoothLeService != null) {
final boolean result = mBluetoothLeService.connect(mDeviceAddress);
Log.d(TAG, "Connect request result=" + result);
}
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(mGattUpdateReceiver);
}
#Override
protected void onDestroy() {
super.onDestroy();
unbindService(mServiceConnection);
mBluetoothLeService = null;
}
private static IntentFilter makeGattUpdateIntentFilter() {
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
return intentFilter;
}
}
BluetoothLeService
public class BluetoothLeService extends Service {
private final static String TAG = BluetoothLeService.class.getSimpleName();
private BluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothAdapter;
private String mBluetoothDeviceAddress;
private BluetoothGatt mBluetoothGatt;
private int mConnectionState = STATE_DISCONNECTED;
private static final int STATE_DISCONNECTED = 0;
private static final int STATE_CONNECTING = 1;
private static final int STATE_CONNECTED = 2;
public final static String ACTION_GATT_CONNECTED = "ACTION_GATT_CONNECTED";
public final static String ACTION_GATT_DISCONNECTED = "ACTION_GATT_DISCONNECTED";
public final static String ACTION_GATT_SERVICES_DISCOVERED = "ACTION_GATT_SERVICES_DISCOVERED";
public final static String ACTION_DATA_AVAILABLE = "ACTION_DATA_AVAILABLE";
public final static String EXTRA_DATA = "EXTRA_DATA";
public final static UUID SERVICE_UUID = UUID.fromString(GattAttributes.BLE_SERVICE);
public final static UUID ALERT_UUID = UUID.fromString(GattAttributes.BLE_ALERT_CHARACTERISTIC);
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.");
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);
}
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
#Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
Log.i("BlueToothService: ", "onCharacteristicRead " + characteristic.toString());
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
}
#Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
Log.i("BlueToothService: ", "onCharacteristicChanged " + characteristic.toString());
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
};
private void broadcastUpdate(final String action) {
final Intent intent = new Intent(action);
Log.i("BlueToothService: ", "BroadcastUpdate ActionOnly: " + action);
sendBroadcast(intent);
}
private void broadcastUpdate(final String action, final BluetoothGattCharacteristic characteristic) {
final Intent intent = new Intent(action);
Log.i("BlueToothService: ", "BroadcastUpdateLong " + characteristic.toString() + " Action:" + action);
intent.putExtra(EXTRA_DATA, characteristic.getValue());
sendBroadcast(intent);
}
public class LocalBinder extends Binder {
BluetoothLeService getService() {
return BluetoothLeService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public boolean onUnbind(Intent intent) {
close();
return super.onUnbind(intent);
}
private final IBinder mBinder = new LocalBinder();
public boolean initialize() {
// For API level 18 and above, get a reference to BluetoothAdapter through
if (mBluetoothManager == null) {
mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
if (mBluetoothManager == null) {
Log.e(TAG, "Unable to initialize BluetoothManager.");
return false;
}
}
mBluetoothAdapter = mBluetoothManager.getAdapter();
if (mBluetoothAdapter == null) {
Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
return false;
}
return true;
}
public boolean connect(final String address) {
if (mBluetoothAdapter == null || address == null) {
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
return false;
}
if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress) && mBluetoothGatt != null) {
Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
if (mBluetoothGatt.connect()) {
mConnectionState = STATE_CONNECTING;
return true;
} else {
return false;
}
}
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
if (device == null) {
Log.w(TAG, "Device not found. Unable to connect.");
return false;
}
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
Log.d(TAG, "Trying to create a new connection.");
mBluetoothDeviceAddress = address;
mConnectionState = STATE_CONNECTING;
return true;
}
public void disconnect() {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.disconnect();
}
public void close() {
if (mBluetoothGatt == null) {
return;
}
mBluetoothGatt.close();
mBluetoothGatt = null;
}
public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.readCharacteristic(characteristic);
}
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
if (SERVICE_UUID.equals(characteristic.getUuid())) {
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(ALERT_UUID);
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
}
}
public BluetoothGattService getSupportedGattService() {
if (mBluetoothGatt == null) return null;
return mBluetoothGatt.getService(SERVICE_UUID);
}
}
Solution Found: Classic Case of mistyping and wrong descriptor UUID. Where I found the answer BLE GATT onCharacteristicChanged not called after subscribing to notification. The mistype was in setCharacteristicNotification method. Changed to ALERT_UUID and to what article has me assuming the correct descriptor UUID
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
if (ALERT_UUID.equals(characteristic.getUuid())) {
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
}
}

How to set buzzer for BLE device in Android

I'm developed Android app to manipulating with BLE device as shown in this
image.
The app can scan and connect the device, but I can't write correct characteristic to buzzer the tag. I write this code to do that:
private static final int ALERT_HIGH = 2;
private static final UUID IMMEDIATE_ALERT_UUID = UUID.fromString("00001802-0000-1000-8000-00805f9b34fb");
private static final UUID ALERT_LEVEL_UUID = UUID.fromString("00002a06-0000-1000-8000-00805f9b34fb");
public void ClickButton(View view)
{
BluetoothGattService alertService = mGatt.getService(IMMEDIATE_ALERT_UUID);
if (alertService == null)
{
Toast.makeText(this, "Immediate Alert service not found!", 1)
.show();
return;
}
BluetoothGattCharacteristic alertLevel = alertService.getCharacteristic(ALERT_LEVEL_UUID);
if (alertLevel == null)
{
Toast.makeText(this, "Alert Level charateristic not found!", 1)
.show();
return;
}
alertLevel.setValue(ALERT_HIGH, BluetoothGattCharacteristic.FORMAT_UINT8, 0);
mGatt.writeCharacteristic(alertLevel);
}
but no action happened!
I found this app iTracing on play store and it worked fine and it can buzzer the ble device.
I don't know where is the missing in my code; and don't know the problem in a previous function I used or in initialize of connection with this device!
Finally, this is the full code I used
public class MainActivity extends Activity {
private BluetoothAdapter mBluetoothAdapter;
private int REQUEST_ENABLE_BT = 1;
private Handler mHandler;
private static final long SCAN_PERIOD = 1000*60;
private BluetoothLeScanner mLEScanner;
private ScanSettings settings;
private List<ScanFilter> filters;
private BluetoothGatt mGatt;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHandler = new Handler();
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();
}
#Override
protected void onResume() {
super.onResume();
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
} else {
if (Build.VERSION.SDK_INT >= 21) {
mLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
settings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.build();
filters = new ArrayList<ScanFilter>();
}
scanLeDevice(true);
}
}
#Override
protected void onPause() {
super.onPause();
if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) {
scanLeDevice(false);
}
}
#Override
protected void onDestroy() {
if (mGatt == null) {
return;
}
mGatt.close();
mGatt = null;
super.onDestroy();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_ENABLE_BT) {
if (resultCode == Activity.RESULT_CANCELED) {
//Bluetooth not enabled.
finish();
return;
}
}
super.onActivityResult(requestCode, resultCode, data);
}
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();
String DeviceAddress = btDevice.getAddress().trim();
if(DeviceAddress.equals("FF:FF:00:01:05:07"))
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);
}
});
}
};
String address;
public void connectToDevice(BluetoothDevice device) {
if (mGatt == null) {
address = device.getAddress();
mGatt = device.connectGatt(this, false, gattCallback);
}
}
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");
mGatt.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());
gatt.readCharacteristic(services.get(1).getCharacteristics().get
(0));
}
#Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic
characteristic, int status) {
Log.i("onCharacteristicRead", characteristic.toString());
gatt.disconnect();
}
};
private static final int ALERT_HIGH = 2;
private static final UUID IMMEDIATE_ALERT_UUID = UUID.fromString("00001802-0000-1000-8000-00805f9b34fb");
private static final UUID ALERT_LEVEL_UUID = UUID.fromString("00002a06-0000-1000-8000-00805f9b34fb");
public void ClickButton(View view)
{
BluetoothGattService alertService = mGatt.getService(IMMEDIATE_ALERT_UUID);
if (alertService == null)
{
Toast.makeText(this, "Immediate Alert service not found!", 1)
.show();
return;
}
BluetoothGattCharacteristic alertLevel = alertService.getCharacteristic(ALERT_LEVEL_UUID);
if (alertLevel == null)
{
Toast.makeText(this, "Alert Level charateristic not found!", 1)
.show();
return;
}
alertLevel.setValue(ALERT_HIGH, BluetoothGattCharacteristic.FORMAT_UINT8, 0);
mGatt.writeCharacteristic(alertLevel);
}
}
I will be grateful for help.
This is how I have done it in my code.
byte[] valToWrite = parseHexStringToBytes("0x0" + alertLevel);
immediateAlertChar.setValue(valToWrite);
boolean val = gatt.writeCharacteristic(immediateAlertChar);
Check also the response in onCharacteristicWrite() method

Android BLE can't receive Gatt Characteristic notification from device

I'm trying to receive a notification from the device when I write a value on a characteristic, but I donĀ“t receive anything. I enable the notification on the characteristic and then I write the value. I've seen that the characteristic in the device have changed its value but I can't get the notification. Here is my code:
DeviceActivity:
public class DevicesActivity extends Activity {
private BLEService mBluetoothLeService;
private String mDeviceAddress;
private boolean mConnected = false;
private BluetoothGattCharacteristic mNotifyCharacteristic;
private final ServiceConnection mServiceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName componentName, IBinder service) {
mBluetoothLeService = ((BLEService.LocalBinder) service).getService();
if (!mBluetoothLeService.initialize()) {
finish();
}
mBluetoothLeService.context = DevicesActivity.this;
mBluetoothLeService.connect(mDeviceAddress);
}
#Override
public void onServiceDisconnected(ComponentName componentName) {
mBluetoothLeService = null;
}
};
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (BLEService.ACTION_GATT_CONNECTED.equals(action)) {
mConnected = true;
invalidateOptionsMenu();
} else if (BLEService.ACTION_GATT_DISCONNECTED.equals(action)) {
mConnected = false;
invalidateOptionsMenu();
} else if (BLEService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
List<BluetoothGattService> servicesList;
servicesList = mBluetoothLeService.getSupportedGattServices();
Iterator<BluetoothGattService> iter = servicesList.iterator();
while (iter.hasNext()) {
BluetoothGattService bService = (BluetoothGattService) iter.next();
if (bService.getUuid().toString().equals(BLEUUID.SERVICE)){
mService = bService;
}
}
} else if (BLEService.ACTION_DATA_AVAILABLE.equals(action)) {
displayData(intent.getStringExtra(BLEService.EXTRA_DATA));
}
}
};
private static final String TAG = "BLEDevice";
public static final String EXTRA_BLUETOOTH_DEVICE = "BT_DEVICE";
private BluetoothAdapter mBTAdapter;
private BluetoothDevice mDevice;
private BluetoothGatt mConnGatt;
private int mStatus;
BluetoothGattService mService;
private EditText pinTxt;
private Button cancelBtn;
private Button unlockBtn;
private Button changePinBtn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.activity_devices);
pinTxt = (EditText) findViewById(R.id.pin_txt);
cancelBtn = (Button) findViewById(R.id.cancel_btn);
unlockBtn = (Button) findViewById(R.id.unlock_btn);
changePinBtn = (Button) findViewById(R.id.change_pin_btn);
unlockBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String aux = pinTxt.getText().toString();
mBluetoothLeService.sendCharacteristic(aux, getBTDeviceExtra());
}
});
mDevice = getBTDeviceExtra();
mDeviceAddress = mDevice.getAddress();
if (mServiceConnection == null){
Log.v("NULL", "mServiceConnection NULL");
}
Intent gattServiceIntent = new Intent(this, BLEService.class);
if (gattServiceIntent==null){
Log.v("NULL", "mServiceConnection NULL");
}
bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
mStatus = BluetoothProfile.STATE_DISCONNECTED;
}
private void displayData(String data) {
if (data != null) {
Toast.makeText(DevicesActivity.this, data, Toast.LENGTH_LONG);
}
}
#Override
protected void onDestroy() {
super.onDestroy();
unbindService(mServiceConnection);
mBluetoothLeService = null;
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(mGattUpdateReceiver);
}
private static IntentFilter makeGattUpdateIntentFilter() {
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BLEService.ACTION_GATT_CONNECTED);
intentFilter.addAction(BLEService.ACTION_GATT_DISCONNECTED);
intentFilter.addAction(BLEService.ACTION_GATT_SERVICES_DISCOVERED);
intentFilter.addAction(BLEService.ACTION_DATA_AVAILABLE);
return intentFilter;
}
#Override
protected void onResume() {
super.onResume();
registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
if (mBluetoothLeService != null) {
final boolean result = mBluetoothLeService.connect(mDeviceAddress);
}
}
private BluetoothDevice getBTDeviceExtra() {
Intent intent = getIntent();
if (intent
== null) { return null;
}
Bundle extras = intent.getExtras();
if (extras == null) {
return null;
}
BluetoothDevice aux = extras.getParcelable(EXTRA_BLUETOOTH_DEVICE);
return aux;
}
BLEService:
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);
}
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
for (BluetoothGattService service : gatt.getServices()) {
if ((service == null) || (service.getUuid() == null)) {
continue;
}
if (BLEUUID.SERVICE.equalsIgnoreCase(service.getUuid().toString())) {
mService = service;
}
}
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
#Override
public void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic,int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
broadcastUpdate(EXTRA_DATA, characteristic);
Log.i("CARAC","CARACTERISTICA LEIDA onCharacteristicRead()");
}
}
#Override
public void onCharacteristicChanged(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic) {
readCharacteristic(characteristic);
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
Log.i("CARAC","CAMBIO EN CARACTERISTICA");
}
};
private void broadcastUpdate(final String action) {
final Intent intent = new Intent(action);
sendBroadcast(intent);
}
#TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
private void broadcastUpdate(final String action,final BluetoothGattCharacteristic characteristic) {
final Intent intent = new Intent(action);
if (PIN_CHARACTERISTIC.equals(characteristic.getUuid())) {
final String pin = characteristic.getStringValue(0);
intent.putExtra(EXTRA_DATA, String.valueOf(pin));
} else {
// For all other profiles, writes the data formatted in HEX.
final byte[] data = characteristic.getValue();
if (data != null && data.length > 0) {
final StringBuilder stringBuilder = new StringBuilder(data.length);
for(byte byteChar : data)
stringBuilder.append(String.format("%02X ", byteChar));
Log.i("RECIBIDO", "RECIBIDOS DATOS");
intent.putExtra(EXTRA_DATA, new String(data) + "\n" + stringBuilder.toString());
}
}
sendBroadcast(intent);
}
public class LocalBinder extends Binder {
BLEService getService() {
return BLEService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public boolean onUnbind(Intent intent) {
// After using a given device, you should make sure that BluetoothGatt.close() is called
// such that resources are cleaned up properly. In this particular example, close() is
// invoked when the UI is disconnected from the Service.
close();
return super.onUnbind(intent);
}
private final IBinder mBinder = new LocalBinder();
public boolean initialize() {
if (mBluetoothManager == null) {
mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
if (mBluetoothManager == null) {
return false;
}
}
mBluetoothAdapter = mBluetoothManager.getAdapter();
if (mBluetoothAdapter == null) {
return false;
}
return true;
}
public boolean connect(final String address) {
if (mBluetoothAdapter == null || address == null) {
return false;
}
// Previously connected device. Try to reconnect.
if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress)
&& mBluetoothGatt != null) {
if (mBluetoothGatt.connect()) {
mConnectionState = STATE_CONNECTING;
return true;
} else {
return false;
}
}
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
if (device == null) {
return false;
}
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
mBluetoothDeviceAddress = address;
mConnectionState = STATE_CONNECTING;
return true;
}
public void disconnect() {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
return;
}
mBluetoothGatt.disconnect();
}
public void close() {
if (mBluetoothGatt == null) {
return;
}
mBluetoothGatt.close();
mBluetoothGatt = null;
Log.e("CIERRE", "CONEXION CERRADA");
}
public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
return;
}
mBluetoothGatt.readCharacteristic(characteristic);
Log.i("READ", "CARACTERISTICA LEIDA");
}
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
return;
}
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
if (PIN_CHARACTERISTIC.equals(characteristic.getUuid())){
BluetoothGattDescriptor descriptor =
new BluetoothGattDescriptor(UUID.nameUUIDFromBytes(BLEUUID.PIN_CHARACTERISTIC_CONFIG_DESCRIPTOR.getBytes()),
BluetoothGattDescriptor.PERMISSION_WRITE_SIGNED);
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
}
}
public List<BluetoothGattService> getSupportedGattServices() {
if (mBluetoothGatt == null) return null;
return mBluetoothGatt.getServices();
}
public void sendCharacteristic(String pin, BluetoothDevice device){
byte[] pinByte = pin.getBytes();
int pinInt = Integer.valueOf(pin);
BluetoothGattCharacteristic ch = (BluetoothGattCharacteristic) mService.getCharacteristic(UUID
.fromString(BLEUUID.PIN_CHARACTERISTIC_UUID));
ch.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
ch.setValue(pin);
Toast.makeText(context, "CARACTERISTICA ASIGNADA", Toast.LENGTH_SHORT).show();
connect(device.getAddress());
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
setCharacteristicNotification(ch, true);
if (mBluetoothGatt.writeCharacteristic(ch)) {
Toast.makeText(context, "CARACTERISTICA ESCRITA", Toast.LENGTH_SHORT).show();
}
}
}
BLEUUID
public class BLEUUID {
// CARACTERISTICA PIN
public static final String SERVICE ="0000fff0-0000-1000-8000-00805f9b34fb";
public static final String PIN_CHARACTERISTIC_UUID="0000fff9-0000-1000-8000-00805f9b34fb";
public static final String PIN_CHARACTERISTIC_CONFIG_DESCRIPTOR="0x2902";
private static HashMap<String, String> attributes = new HashMap();
static {
attributes.put(SERVICE, "Service");
attributes.put(PIN_CHARACTERISTIC_UUID, "Pin");
}
When I debug, onCharacteristicChange() never executes.
Somebody knows where's the problem
Here is the general pattern for how things need to work with BLE on Android:
You try to connect
You get a callback indicating it is connected
You discover services
You are told services are discovered
You get the characteristics
For each characteristic you get the descriptors
For the descriptor you set it to enable notification/indication with BluetoothGattDescriptor.setValue()
You write the descriptor with BluetoothGatt.writeDescriptor()
You enable notifications for the characteristic locally with BluetoothGatt.setCharacteristicNotification(). Without this you won't get called back.
You get notification that the descriptor was written
Now you can write data to the characteristic. All of the characteristic and descriptor configuration has do be done before anything is written to any characteristic.

Categories

Resources