Hey I am working on application in which I am using BLE to transfer User ID from mobile to mobile by using my application when they interact with each other , which means in one mobile my app will work as Peripheral Mode and in other it will work as a Central mode. So what I have done is I open my first app as a Peripheral Mode which starts advertising and other as Central which starts a service in background to scan device and make connection to read data. This functionality works fine I send message(User ID) from Peripheral to central it pops on central device. Now I want to send User ID of Central Mode device to Peripheral.
As per my understanding, In BLE we cannot send data from central to peripheral we can only scan from central. But I heard that we can write characteristics from Peripheral to get some response in back So is it possible that i can send my Used ID from Central to Peripheral through response or any other alternate way is possible?
I want to do this
I am just new in BLE so I have no idea how to perform this functionality. I am sharing my code that what I am doing below :
SO Central Mode or You say scanning which I start in background service is:
GATT Service
public class GattService extends Service {
private static int NOTIFICATION_ID = 0;
public static final ParcelUuid UUID = ParcelUuid.fromString("0000FED8-0000-1000-8000-00805F9B34FB");
public static final java.util.UUID SERVICE_UUID = java.util.UUID.fromString("00001111-0000-1000-8000-00805F9B34FB");
public static final java.util.UUID CHAR_UUID = java.util.UUID.fromString("00002222-0000-1000-8000-00805F9B34FB");
private BluetoothAdapter bluetoothAdapter;
private BluetoothGattServer server;
private BluetoothLeAdvertiser bluetoothLeAdvertiser;
private boolean start;
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
setupBluetooth();
return Service.START_STICKY;
}
private void setupBluetooth() {
BluetoothManager bluetoothManager = (BluetoothManager) this.getApplicationContext().getSystemService(Context.BLUETOOTH_SERVICE);
server = bluetoothManager.openGattServer(this, serverCallback);
initServer();
bluetoothAdapter = bluetoothManager.getAdapter();
advertise();
}
private void initServer() {
BluetoothGattService service = new BluetoothGattService(SERVICE_UUID, BluetoothGattService.SERVICE_TYPE_PRIMARY);
BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(CHAR_UUID, BluetoothGattCharacteristic.PROPERTY_WRITE | BluetoothGattCharacteristic.PROPERTY_READ, BluetoothGattCharacteristic.PERMISSION_READ | BluetoothGattCharacteristic.PERMISSION_WRITE);
service.addCharacteristic(characteristic);
server.addService(service);
}
private void advertise() {
bluetoothLeAdvertiser = bluetoothAdapter.getBluetoothLeAdvertiser();
AdvertiseData advertisementData = getAdvertisementData();
AdvertiseSettings advertiseSettings = getAdvertiseSettings();
bluetoothLeAdvertiser.startAdvertising(advertiseSettings, advertisementData, advertiseCallback);
start = true;
}
private AdvertiseData getAdvertisementData() {
AdvertiseData.Builder builder = new AdvertiseData.Builder();
builder.setIncludeTxPowerLevel(true);
builder.addServiceUuid(UUID);
bluetoothAdapter.setName("BLE client");
builder.setIncludeDeviceName(true);
return builder.build();
}
private AdvertiseSettings getAdvertiseSettings() {
AdvertiseSettings.Builder builder = new AdvertiseSettings.Builder();
builder.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_BALANCED);
builder.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH);
builder.setConnectable(true);
return builder.build();
}
private final AdvertiseCallback advertiseCallback = new AdvertiseCallback() {
#SuppressLint("Override")
#Override
public void onStartSuccess(AdvertiseSettings advertiseSettings) {
final String message = "Advertisement successful";
sendNotification(message);
}
#SuppressLint("Override")
#Override
public void onStartFailure(int i) {
final String message = "Advertisement failed error code: " + i;
sendNotification(message);
}
};
private BluetoothGattServerCallback serverCallback = new BluetoothGattServerCallback() {
#Override
public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
super.onConnectionStateChange(device, status, newState);
if (newState == BluetoothProfile.STATE_CONNECTED) {
sendNotification("Client connected");
}
}
#Override
public void onServiceAdded(int status, BluetoothGattService service) {
super.onServiceAdded(status, service);
}
#Override
public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicReadRequest(device, requestId, offset, characteristic);
server.sendResponse(device, requestId, BluetoothGatt.GATT_FAILURE, 0, null);
}
#Override
public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
super.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value);
byte[] bytes = value;
String message = new String(bytes);
sendNotification(message);
if (characteristic.getUuid().equals(CHAR_UUID)) {
server.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, null);
}
int length = value.length;
byte[] reversed = new byte[length];
for (int i = 0; i < length; i++) {
reversed[i] = value[length - (i + 1)];
}
characteristic.setValue(reversed);
server.notifyCharacteristicChanged(device, characteristic, true);
}
#Override
public void onDescriptorReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattDescriptor descriptor) {
super.onDescriptorReadRequest(device, requestId, offset, descriptor);
}
#Override
public void onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
super.onDescriptorWriteRequest(device, requestId, descriptor, preparedWrite, responseNeeded, offset, value);
}
#Override
public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) {
super.onExecuteWrite(device, requestId, execute);
}
#Override
public void onNotificationSent(BluetoothDevice device, int status) {
super.onNotificationSent(device, status);
}
#Override
public void onMtuChanged(BluetoothDevice device, int mtu) {
super.onMtuChanged(device, mtu);
}
};
#Override
public void onDestroy() {
if (start) {
bluetoothLeAdvertiser.stopAdvertising(advertiseCallback);
}
super.onDestroy();
}
private void sendNotification(String message) {
NotificationManager notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
int notificationId = 1;
String channelId = "channel-01";
String channelName = "Channel Name";
int importance = NotificationManager.IMPORTANCE_HIGH;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel mChannel = new NotificationChannel(
channelId, channelName, importance);
notificationManager.createNotificationChannel(mChannel);
}
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(getString(R.string.app_name))
.setContentText(message)
.setAutoCancel(true);
Intent intent = new Intent(this, MainActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addNextIntent(intent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
notificationManager.notify(notificationId, mBuilder.build());
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
And my Peripheral device which send Characteristic after successful connection is:
public class ServicesList extends AppCompatActivity implements AdapterView.OnItemClickListener {
private ListView servicesList;
private LinearLayout messageContainer;
private BluetoothDevice device;
private List<String> servicesListNames;
private ArrayAdapter<String> servicesAdapter;
private Handler handler;
private List<BluetoothGattService> services;
private BluetoothGatt currentGatt;
private EditText message;
private Button send;
private BluetoothGattCharacteristic characteristic;
private ProgressDialog dialog;
public static final java.util.UUID DES_UUID = java.util.UUID.fromString("00003333-0000-1000-8000-00805F9B34FB");
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.services_list);
handler = new Handler();
dialog = new ProgressDialog(this);
dialog.setCancelable(false);
dialog.setMessage("Loading");
device = getIntent().getExtras().getParcelable("device");
servicesList = (ListView) findViewById(R.id.services_list);
messageContainer = (LinearLayout) findViewById(R.id.message_container);
message = (EditText) findViewById(R.id.message);
send = (Button) findViewById(R.id.send);
currentGatt = device.connectGatt(this, false, gattCallback);
dialog.show();
servicesListNames = new ArrayList<>();
servicesAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, servicesListNames);
servicesList.setAdapter(servicesAdapter);
servicesList.setOnItemClickListener(this);
send.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(!message.getText().toString().trim().isEmpty()) {
characteristic.setValue(message.getText().toString().getBytes());
currentGatt.writeCharacteristic(characteristic);
message.setText("");
}
}
});
}
private BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
if(newState == BluetoothProfile.STATE_CONNECTED) {
currentGatt.discoverServices();
}else{
if(dialog.isShowing()){
handler.post(new Runnable() {
#Override
public void run() {
dialog.hide();
}
});
}
}
}
#Override
public void onServicesDiscovered(final BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
services = currentGatt.getServices();
for(BluetoothGattService service : services){
Log.d("Khurram", "Uuid = " + service.getUuid().toString());
servicesListNames.add(Helper.getServiceName(service.getUuid().toString()));
handler.post(new Runnable() {
#Override
public void run() {
servicesAdapter.notifyDataSetChanged();
}
});
}
if (dialog.isShowing()){
handler.post(new Runnable() {
#Override
public void run() {
dialog.hide();
}
});
}
}
#Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
// log("Characteristic read successfully");
readCharacteristic(characteristic);
} else {
// logError("Characteristic read unsuccessful, status: " + status);
// Trying to read from the Time Characteristic? It doesnt have the property or
permissions
// set to allow this. Normally this would be an error and you would want to:
// disconnectGattServer();
}
}
#Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
int status) {
super.onCharacteristicWrite(gatt, characteristic, status);
gatt.executeReliableWrite();
}
#Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic
characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
readCharacteristic(characteristic);
}
#Override
public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status)
{
super.onDescriptorRead(gatt, descriptor, status);
}
#Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status)
{
super.onDescriptorWrite(gatt, descriptor, status);
}
#Override
public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
super.onReliableWriteCompleted(gatt, status);
}
#Override
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
super.onReadRemoteRssi(gatt, rssi, status);
}
#Override
public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
super.onMtuChanged(gatt, mtu, status);
}
};
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if(services != null){
BluetoothGattService notificationService = services.get(position);
if(notificationService.getUuid().equals(GattService.SERVICE_UUID)){
characteristic = notificationService.getCharacteristic(GattService.CHAR_UUID);
if(characteristic != null) {
messageContainer.setVisibility(View.VISIBLE);
}
}else{
Toast.makeText(this, "Testing", Toast.LENGTH_SHORT).show();
}
}
}
private void readCharacteristic(BluetoothGattCharacteristic characteristic) {
byte[] messageBytes = characteristic.getValue();
log("Read: " + StringUtils.byteArrayInHexFormat(messageBytes));
String message = StringUtils.stringFromBytes(messageBytes);
if (message == null) {
logError("Unable to convert bytes to string");
Toast.makeText(this, "Unable to convert bytes to string", Toast.LENGTH_SHORT).show();
return;
}
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
}
So what I am doing is I have a EditText in peripheral in which i enter the text like User ID and I am returning it back from service as response after reversing it and show notification in Central Mode.
But I am not able to get the response Can you guys help me please ?
If you guys know my scenario you can also assist me with new way through BLE by which I can exchange data between 2 android phones.
Thanks,
Related
I have create BLE app which includes client and server app. The code is running successfully. Now i want to run server code as a service so that Bluetooth is open every time and it can be searched by client app whenever required. The code used for server is as below. Please guide me to use this code as a service.
public class ServerActivity extends AppCompatActivity {
private static final String TAG = "ServerActivity";
private ActivityServerBinding mBinding;
private Handler mHandler;
private Handler mLogHandler;
private List<BluetoothDevice> mDevices;
private Map<String, byte[]> mClientConfigurations;
private BluetoothGattServer mGattServer;
private BluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothAdapter;
private BluetoothLeAdvertiser mBluetoothLeAdvertiser;
// Lifecycle
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHandler = new Handler();
mLogHandler = new Handler(Looper.getMainLooper());
mDevices = new ArrayList<>();
mClientConfigurations = new HashMap<>();
mBluetoothManager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
mBluetoothAdapter = mBluetoothManager.getAdapter();
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_server);
mBinding.restartServerButton.setOnClickListener(v -> restartServer());
}
#Override
protected void onResume() {
super.onResume();
// Check if bluetooth is enabled
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
// Request user to enable it
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivity(enableBtIntent);
finish();
return;
}
// Check low energy support
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
// Get a newer device
log("No LE Support.");
finish();
return;
}
// Check advertising
if (!mBluetoothAdapter.isMultipleAdvertisementSupported()) {
// Unable to run the server on this device, get a better device
log("No Advertising Support.");
finish();
return;
}
mBluetoothLeAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser();
GattServerCallback gattServerCallback = new GattServerCallback();
mGattServer = mBluetoothManager.openGattServer(this, gattServerCallback);
Bundle bundle = getIntent().getExtras();
String plate_name = bundle.getString("PLATE_NAME");
mBluetoothAdapter.setName(plate_name);
Toast.makeText(getApplicationContext(),"PLATE NAME "+plate_name,Toast.LENGTH_LONG).show();
#SuppressLint("HardwareIds")
String deviceInfo = "Device Info"
+ "\nName: " + mBluetoothAdapter.getName()
+ "\nAddress: " + mBluetoothAdapter.getAddress();
mBinding.serverDeviceInfoTextView.setText(deviceInfo);
setupServer();
startAdvertising();
}
#Override
protected void onPause() {
super.onPause();
stopAdvertising();
stopServer();
}
// GattServer
private void setupServer() {
BluetoothGattService service = new BluetoothGattService(SERVICE_UUID, BluetoothGattService.SERVICE_TYPE_PRIMARY);
// Write characteristic
BluetoothGattCharacteristic writeCharacteristic = new BluetoothGattCharacteristic(CHARACTERISTIC_ECHO_UUID,
BluetoothGattCharacteristic.PROPERTY_WRITE,
// Somehow this is not necessary, the client can still enable notifications
// | BluetoothGattCharacteristic.PROPERTY_NOTIFY,
BluetoothGattCharacteristic.PERMISSION_WRITE);
// Characteristic with Descriptor
BluetoothGattCharacteristic notifyCharacteristic = new BluetoothGattCharacteristic(CHARACTERISTIC_TIME_UUID,
// Somehow this is not necessary, the client can still enable notifications
// BluetoothGattCharacteristic.PROPERTY_NOTIFY,
0, 0);
BluetoothGattDescriptor clientConfigurationDescriptor = new BluetoothGattDescriptor(CLIENT_CONFIGURATION_DESCRIPTOR_UUID,
BluetoothGattDescriptor.PERMISSION_READ | BluetoothGattDescriptor.PERMISSION_WRITE);
clientConfigurationDescriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
notifyCharacteristic.addDescriptor(clientConfigurationDescriptor);
service.addCharacteristic(writeCharacteristic);
service.addCharacteristic(notifyCharacteristic);
mGattServer.addService(service);
}
private void stopServer() {
if (mGattServer != null) {
mGattServer.close();
}
}
private void restartServer() {
stopAdvertising();
stopServer();
setupServer();
startAdvertising();
}
// Advertising
private void startAdvertising() {
if (mBluetoothLeAdvertiser == null) {
return;
}
AdvertiseSettings settings = new AdvertiseSettings.Builder()
.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_BALANCED)
.setConnectable(true)
.setTimeout(0)
.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_LOW)
.build();
ParcelUuid parcelUuid = new ParcelUuid(SERVICE_UUID);
AdvertiseData data = new AdvertiseData.Builder()
.setIncludeDeviceName(true)
.addServiceUuid(parcelUuid)
.build();
mBluetoothLeAdvertiser.startAdvertising(settings, data, mAdvertiseCallback);
}
private void stopAdvertising() {
if (mBluetoothLeAdvertiser != null) {
mBluetoothLeAdvertiser.stopAdvertising(mAdvertiseCallback);
}
}
private AdvertiseCallback mAdvertiseCallback = new AdvertiseCallback() {
#Override
public void onStartSuccess(AdvertiseSettings settingsInEffect) {
log("Peripheral advertising started.");
}
#Override
public void onStartFailure(int errorCode) {
log("Peripheral advertising failed: " + errorCode);
}
};
// Notifications
private void notifyCharacteristicTime(byte[] value) {
notifyCharacteristic(value, CHARACTERISTIC_TIME_UUID);
}
private void notifyCharacteristic(byte[] value, UUID uuid) {
mHandler.post(() -> {
BluetoothGattService service = mGattServer.getService(SERVICE_UUID);
BluetoothGattCharacteristic characteristic = service.getCharacteristic(uuid);
log("Notifying characteristic " + characteristic.getUuid().toString()
+ ", new value: " + StringUtils.byteArrayInHexFormat(value));
characteristic.setValue(value);
// Indications require confirmation, notifications do not
boolean confirm = BluetoothUtils.requiresConfirmation(characteristic);
for (BluetoothDevice device : mDevices) {
if (clientEnabledNotifications(device, characteristic)) {
mGattServer.notifyCharacteristicChanged(device, characteristic, confirm);
}
}
});
}
private boolean clientEnabledNotifications(BluetoothDevice device, BluetoothGattCharacteristic characteristic) {
List<BluetoothGattDescriptor> descriptorList = characteristic.getDescriptors();
BluetoothGattDescriptor descriptor = BluetoothUtils.findClientConfigurationDescriptor(descriptorList);
if (descriptor == null) {
// There is no client configuration descriptor, treat as true
return true;
}
String deviceAddress = device.getAddress();
byte[] clientConfiguration = mClientConfigurations.get(deviceAddress);
if (clientConfiguration == null) {
// Descriptor has not been set
return false;
}
byte[] notificationEnabled = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE;
return clientConfiguration.length == notificationEnabled.length
&& (clientConfiguration[0] & notificationEnabled[0]) == notificationEnabled[0]
&& (clientConfiguration[1] & notificationEnabled[1]) == notificationEnabled[1];
}
// Gatt Server Actions
public void log(String msg) {
Log.d(TAG, msg);
mLogHandler.post(() -> {
mBinding.viewServerLog.logTextView.append(msg + "\n");
mBinding.viewServerLog.logScrollView.post(() -> mBinding.viewServerLog.logScrollView.fullScroll(View.FOCUS_DOWN));
if (msg.contains("Open")) {
ToneGenerator toneGen1 = new ToneGenerator(AudioManager.STREAM_MUSIC, 100);
toneGen1.startTone(ToneGenerator.TONE_CDMA_PIP, 150);
} else if (msg.contains("Close")) {
ToneGenerator toneGen1 = new ToneGenerator(AudioManager.STREAM_MUSIC, 100);
toneGen1.startTone(ToneGenerator.TONE_CDMA_PIP, 150);
toneGen1.startTone(ToneGenerator.TONE_CDMA_PIP, 300);
}
});
}
public void addDevice(BluetoothDevice device) {
log("Device added: " + device.getAddress());
mHandler.post(() -> mDevices.add(device));
}
public void removeDevice(BluetoothDevice device) {
log("Device removed: " + device.getAddress());
mHandler.post(() -> {
mDevices.remove(device);
String deviceAddress = device.getAddress();
mClientConfigurations.remove(deviceAddress);
});
}
public void addClientConfiguration(BluetoothDevice device, byte[] value) {
String deviceAddress = device.getAddress();
mClientConfigurations.put(deviceAddress, value);
}
public void sendResponse(BluetoothDevice device, int requestId, int status, int offset, byte[] value) {
mGattServer.sendResponse(device, requestId, status, 0, null);
}
public void notifyCharacteristicEcho(byte[] value) {
notifyCharacteristic(value, CHARACTERISTIC_ECHO_UUID);
}
// Gatt Callback
private class GattServerCallback extends BluetoothGattServerCallback {
#Override
public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
super.onConnectionStateChange(device, status, newState);
log("onConnectionStateChange " + device.getAddress()
+ "\nstatus " + status
+ "\nnewState " + newState);
if (newState == BluetoothProfile.STATE_CONNECTED) {
addDevice(device);
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
removeDevice(device);
}
}
// The Gatt will reject Characteristic Read requests that do not have the permission set,
// so there is no need to check inside the callback
#Override
public void onCharacteristicReadRequest(BluetoothDevice device,
int requestId,
int offset,
BluetoothGattCharacteristic characteristic) {
super.onCharacteristicReadRequest(device, requestId, offset, characteristic);
log("onCharacteristicReadRequest " + characteristic.getUuid().toString());
if (BluetoothUtils.requiresResponse(characteristic)) {
// Unknown read characteristic requiring response, send failure
sendResponse(device, requestId, BluetoothGatt.GATT_FAILURE, 0, null);
}
// Not one of our characteristics or has NO_RESPONSE property set
}
// The Gatt will reject Characteristic Write requests that do not have the permission set,
// so there is no need to check inside the callback
#Override
public void onCharacteristicWriteRequest(BluetoothDevice device,
int requestId,
BluetoothGattCharacteristic characteristic,
boolean preparedWrite,
boolean responseNeeded,
int offset,
byte[] value) {
super.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value);
log("onCharacteristicWriteRequest" + characteristic.getUuid().toString()
+ "\nReceived: " + StringUtils.stringFromBytes(value));
if (CHARACTERISTIC_ECHO_UUID.equals(characteristic.getUuid())) {
sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, null);
// Reverse message to differentiate original message & response
byte[] response = ByteUtils.reverse(value);
characteristic.setValue(response);
log("Sending: " + StringUtils.byteArrayInHexFormat(response));
notifyCharacteristicEcho(response);
}
}
// The Gatt will reject Descriptor Read requests that do not have the permission set,
// so there is no need to check inside the callback
#Override
public void onDescriptorReadRequest(BluetoothDevice device,
int requestId,
int offset,
BluetoothGattDescriptor descriptor) {
super.onDescriptorReadRequest(device, requestId, offset, descriptor);
log("onDescriptorReadRequest" + descriptor.getUuid().toString());
}
// The Gatt will reject Descriptor Write requests that do not have the permission set,
// so there is no need to check inside the callback
#Override
public void onDescriptorWriteRequest(BluetoothDevice device,
int requestId,
BluetoothGattDescriptor descriptor,
boolean preparedWrite,
boolean responseNeeded,
int offset,
byte[] value) {
super.onDescriptorWriteRequest(device, requestId, descriptor, preparedWrite, responseNeeded, offset, value);
log("onDescriptorWriteRequest: " + descriptor.getUuid().toString()
+ "\nvalue: " + StringUtils.stringFromBytes(value));
if (CLIENT_CONFIGURATION_DESCRIPTOR_UUID.equals(descriptor.getUuid())) {
addClientConfiguration(device, value);
sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, null);
}
}
#Override
public void onNotificationSent(BluetoothDevice device, int status) {
super.onNotificationSent(device, status);
log("onNotificationSent");
}
}
}
Use Foreground service with persistent notification. Your service will be keep on running.
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.
My gattServer advertise some data with paired bluetooth device and I run this gattServer with service.Everthing is well with Bluetooth state on but I turned off bluetooth and on again throw exception this line
sGattServer.notifyCharacteristicChanged(device, getCharacteristic(Constants.NOTIFICATION_SOURCE), false);
This is my connection Method
BluetoothAdapter bleAdapter = ((BluetoothManager) context.getSystemService(BLUETOOTH_SERVICE)).getAdapter();
final Set<BluetoothDevice> pairedDevices = bleAdapter.getBondedDevices();
for (BluetoothDevice d : pairedDevices) {
d.connectGatt(context, true, new BluetoothGattCallback() {
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
#Override
public void onConnectionStateChange(BluetoothGatt
gatt, int status, int newState) {
switch (newState) {
case BluetoothProfile.STATE_CONNECTED:
gatt.getServices();
break;
case BluetoothProfile.STATE_DISCONNECTED:
if (gatt !=null){
gatt.close();
gatt.disconnect();
gatt.connect();
}
break;
}
}
});
}
Stuck trace here:
10-23 10:04:53.978 27768-27768/E/BluetoothGattServer: android.os.DeadObjectException
at android.os.BinderProxy.transactNative(Native Method)
at android.os.BinderProxy.transact(Binder.java:496)
at android.bluetooth.IBluetoothGatt$Stub$Proxy.sendNotification(IBluetoothGatt.java:1482)
at android.bluetooth.BluetoothGattServer.notifyCharacteristicChanged(BluetoothGattServer.java:539)
When Bluetooth is turned off, Android restarts the Bluetooth stack to clean up its state. Kind of like cracking a walnut with a 40lb sledge hammer. See the Logcat
2019-08-02 11:56:29.274 10736-10736/? D/BluetoothAdapterService: onDestroy()
2019-08-02 11:56:29.281 10736-10736/? I/BluetoothAdapterService: Force exit to cleanup internal state in Bluetooth stack
In your GattServer Service you need to recreate the BluetoothGattServer object when the Bluetooth is powered back on.
You did not show the code from your service, which is where the problem lies, but you will need to do something like the following. Create a method createServerGattService which defines the service UUID and characteristics of you GATT server service, then registers it with the BLE stack. You already have this because you say the GATT server works fine until you turn the Bluetooth adapter off snd on.
Add a Bluetooth adapter power state receiver to your service:
private BluetoothGattServer gattServer;
private final BroadcastReceiver m_bluetoothAdapterPowerStateeceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
BluetoothAdapter.ERROR);
switch (state) {
case BluetoothAdapter.STATE_OFF:
gattServer = null;
break;
case BluetoothAdapter.STATE_TURNING_OFF:
gattServer.close();
break;
case BluetoothAdapter.STATE_ON:
gattServer = createServerGattService();
break;
case BluetoothAdapter.STATE_TURNING_ON:
break;
}
}
}
};
In the onCreate() method of your service, register the receiver and instantiate your gatt server if the Bluetooth adapter is powered on:
#Override
public void onCreate() {
super.onCreate();
IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
registerReceiver(m_bluetoothAdapterPowerStateeceiver, filter);
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) {
gattServer = createServerGattService();
}
}
In the onDestroy() method of your service, remove the receiver and close the GATT server connection:
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(m_bluetoothAdapterPowerStateeceiver);
if(gattServer != null)
gattServer.close();
}
For completeness sake of the answer, the createServerGattService() should look something like this:
private BluetoothGattServer createServerGattService() {
BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
BluetoothGattServer server = null;
if(bluetoothManager != null) {
server = bluetoothManager.openGattServer(this, new BluetoothGattServerCallback() {
#Override
public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
super.onConnectionStateChange(device, status, newState);
}
#Override
public void onServiceAdded(int status, BluetoothGattService service) {
super.onServiceAdded(status, service);
}
#Override
public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicReadRequest(device, requestId, offset, characteristic);
}
#Override
public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
super.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value);
}
#Override
public void onDescriptorReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattDescriptor descriptor) {
super.onDescriptorReadRequest(device, requestId, offset, descriptor);
}
#Override
public void onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
super.onDescriptorWriteRequest(device, requestId, descriptor, preparedWrite, responseNeeded, offset, value);
}
#Override
public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) {
super.onExecuteWrite(device, requestId, execute);
}
#Override
public void onNotificationSent(BluetoothDevice device, int status) {
super.onNotificationSent(device, status);
}
#Override
public void onMtuChanged(BluetoothDevice device, int mtu) {
super.onMtuChanged(device, mtu);
}
#Override
public void onPhyUpdate(BluetoothDevice device, int txPhy, int rxPhy, int status) {
super.onPhyUpdate(device, txPhy, rxPhy, status);
}
#Override
public void onPhyRead(BluetoothDevice device, int txPhy, int rxPhy, int status) {
super.onPhyRead(device, txPhy, rxPhy, status);
}
});
BluetoothGattService service = new BluetoothGattService(serviceUuid, BluetoothGattService.SERVICE_TYPE_PRIMARY);
BluetoothGattCharacteristic characteristic1 = new BluetoothGattCharacteristic(
characteristic1Uuid,
BluetoothGattCharacteristic.PROPERTY_READ,
BluetoothGattCharacteristic.PERMISSION_READ);
service.addCharacteristic(characteristic1);
server.addService(service);
}
return server;
}
I using MI BAND 2 BLE. I made demo app for ready characteristics from BLE. My sample code here
package id.aashari.code.miband2.Activities;
public class MainActivity extends Activity {
Boolean isListeningHeartRate = false;
BluetoothAdapter bluetoothAdapter;
BluetoothGatt bluetoothGatt;
BluetoothDevice bluetoothDevice;
Button btnStartConnecting, btnGetBatteryInfo, btnGetHeartRate, btnWalkingInfo, btnStartVibrate, btnStopVibrate;
EditText txtPhysicalAddress;
TextView txtState, txtByte;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initializeObjects();
initilaizeComponents();
initializeEvents();
getBoundedDevice();
}
void getBoundedDevice() {
Set<BluetoothDevice> boundedDevice = bluetoothAdapter.getBondedDevices();
for (BluetoothDevice bd : boundedDevice) {
if (bd.getName().contains("MI Band 2")) {
txtPhysicalAddress.setText(bd.getAddress());
}
}
}
void initializeObjects() {
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
}
void initilaizeComponents() {
btnStartConnecting = (Button) findViewById(R.id.btnStartConnecting);
btnGetBatteryInfo = (Button) findViewById(R.id.btnGetBatteryInfo);
btnWalkingInfo = (Button) findViewById(R.id.btnWalkingInfo);
btnStartVibrate = (Button) findViewById(R.id.btnStartVibrate);
btnStopVibrate = (Button) findViewById(R.id.btnStopVibrate);
btnGetHeartRate = (Button) findViewById(R.id.btnGetHeartRate);
txtPhysicalAddress = (EditText) findViewById(R.id.txtPhysicalAddress);
txtState = (TextView) findViewById(R.id.txtState);
txtByte = (TextView) findViewById(R.id.txtByte);
}
void initializeEvents() {
btnStartConnecting.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startConnecting();
}
});
btnGetBatteryInfo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getBatteryStatus();
}
});
btnStartVibrate.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startVibrate();
}
});
btnStopVibrate.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
stopVibrate();
}
});
btnGetHeartRate.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startScanHeartRate();
}
});
}
void startConnecting() {
String address = txtPhysicalAddress.getText().toString();
bluetoothDevice = bluetoothAdapter.getRemoteDevice(address);
Log.v("test", "Connecting to " + address);
Log.v("test", "Device name " + bluetoothDevice.getName());
bluetoothGatt = bluetoothDevice.connectGatt(this, true, bluetoothGattCallback);
}
void stateConnected() {
bluetoothGatt.discoverServices();
txtState.setText("Connected");
}
void stateDisconnected() {
bluetoothGatt.disconnect();
txtState.setText("Disconnected");
}
void startScanHeartRate() {
txtByte.setText("...");
BluetoothGattCharacteristic bchar = bluetoothGatt.getService(CustomBluetoothProfile.HeartRate.service)
.getCharacteristic(CustomBluetoothProfile.HeartRate.controlCharacteristic);
bchar.setValue(new byte[]{21, 2, 1});
bluetoothGatt.writeCharacteristic(bchar);
}
void listenHeartRate() {
BluetoothGattCharacteristic bchar = bluetoothGatt.getService(CustomBluetoothProfile.HeartRate.service)
.getCharacteristic(CustomBluetoothProfile.HeartRate.measurementCharacteristic);
bluetoothGatt.setCharacteristicNotification(bchar, true);
BluetoothGattDescriptor descriptor = bchar.getDescriptor(CustomBluetoothProfile.HeartRate.descriptor);
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
bluetoothGatt.writeDescriptor(descriptor);
isListeningHeartRate = true;
}
void getBatteryStatus() {
txtByte.setText("...");
BluetoothGattCharacteristic bchar = bluetoothGatt.getService(CustomBluetoothProfile.Basic.service)
.getCharacteristic(CustomBluetoothProfile.Basic.batteryCharacteristic);
if (!bluetoothGatt.readCharacteristic(bchar)) {
Toast.makeText(this, "Failed get battery info", Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(getApplicationContext(),"Successfully readed", Toast.LENGTH_LONG).show();
}
}
void startVibrate() {
BluetoothGattCharacteristic bchar = bluetoothGatt.getService(CustomBluetoothProfile.AlertNotification.service)
.getCharacteristic(CustomBluetoothProfile.AlertNotification.alertCharacteristic);
bchar.setValue(new byte[]{2});
if (!bluetoothGatt.writeCharacteristic(bchar)) {
Toast.makeText(this, "Failed start vibrate", Toast.LENGTH_SHORT).show();
}
}
void stopVibrate() {
BluetoothGattCharacteristic bchar = bluetoothGatt.getService(CustomBluetoothProfile.AlertNotification.service)
.getCharacteristic(CustomBluetoothProfile.AlertNotification.alertCharacteristic);
bchar.setValue(new byte[]{0});
if (!bluetoothGatt.writeCharacteristic(bchar)) {
Toast.makeText(this, "Failed stop vibrate", Toast.LENGTH_SHORT).show();
}
}
final BluetoothGattCallback bluetoothGattCallback = new BluetoothGattCallback() {
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
Log.v("test", "onConnectionStateChange");
if (newState == BluetoothProfile.STATE_CONNECTED) {
stateConnected();
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
stateDisconnected();
}
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
Log.v("test", "onServicesDiscovered");
listenHeartRate();
}
#Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
Log.v("test", "onCharacteristicRead");
byte[] data = characteristic.getValue();
txtByte.setText(Arrays.toString(data));
}
#Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicWrite(gatt, characteristic, status);
Log.v("test", "onCharacteristicWrite");
}
#Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
Log.v("test", "onCharacteristicChanged");
byte[] data = characteristic.getValue();
txtByte.setText(Arrays.toString(data));
}
#Override
public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
super.onDescriptorRead(gatt, descriptor, status);
Log.v("test", "onDescriptorRead");
}
#Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
super.onDescriptorWrite(gatt, descriptor, status);
Log.v("test", "onDescriptorWrite");
}
#Override
public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
super.onReliableWriteCompleted(gatt, status);
Log.v("test", "onReliableWriteCompleted");
}
#Override
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
super.onReadRemoteRssi(gatt, rssi, status);
Log.v("test", "onReadRemoteRssi");
}
#Override
public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
super.onMtuChanged(gatt, mtu, status);
Log.v("test", "onMtuChanged");
}
};
}
this is the output
I can read characteristics but it only show byte value I converted into String but it value is always same.example I read battery level it only showing byte type value i attached output screen
I trying to do same with Mi Band 3.
My code is:
private void connect(){
String macAddress = "E9:FD:0C:CB:67:2C";
bleDevice = rxBleClient.getBleDevice(macAddress);
connectDisposable = bleDevice.establishConnection(true)
.subscribe(
rxBleConnection -> {
// All GATT operations are done through the rxBleConnection.
Log.d(TAG, "Is connected");
rxBleConnection.readCharacteristic(UUID_CHARACTERISTIC_HEART_RATE_MEASUREMENT).subscribe(
bytes -> {
Log.d(TAG, "Data " + bytes);
},
throwable -> {
Log.d(TAG, "Error " + throwable.getMessage());
}
);
},
throwable -> {
// Handle an error here.
Log.d(TAG, "Error " + throwable.getMessage());
}
);
}
Can you provide any explanations how you solved the problem.
I'm developing an Android app than can transmit commands to a 4.0 Bluetooth serial device. I am suppose to get a response from the device. I was able to connect to the device and send the command, but how can I get this response? I have tried with a BluetoothGattServerCallback but it doesn`t work. This is my code:
public class MainActivity extends Activity {
private Handler handler;
private static final long SCAN_PERIOD = 12000;
private BluetoothAdapter btAdapter;
private LinearLayout pairedDevicesList;
private LinearLayout availableDevicesList;
private ProgressBar progressBar;
private BluetoothGatt gatt;
private List<BluetoothGattService> services;
private BluetoothGattServer gattServer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pairedDevicesList = (LinearLayout) findViewById(R.id.paired_devices);
availableDevicesList = (LinearLayout) findViewById(R.id.available_devices);
progressBar = (ProgressBar) findViewById(R.id.progress);
}
#Override
public void onResume() {
handler = new Handler();
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
gattServer = bluetoothManager.openGattServer(this, new BluetoothGattServerCallback() {
#Override
public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
super.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value);
Log.i(getClass().getSimpleName(), "onCharacteristicWriteRequest");
}
#Override
public void onNotificationSent(BluetoothDevice device, int status) {
super.onNotificationSent(device, status);
Log.i(getClass().getSimpleName(), "onNotificationSent");
}
});
btAdapter = bluetoothManager.getAdapter();
final BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
pairedDevicesList.removeAllViews();
final Set<BluetoothDevice> pairedDevices = btAdapter.getBondedDevices();
if (pairedDevices != null) {
for (final BluetoothDevice pairedDevice : pairedDevices) {
addListItem(pairedDevicesList, pairedDevice);
}
}
scanLeDevice(true);
super.onResume();
}
private void scanLeDevice(final boolean enable) {
if (enable) {
// Stops scanning after a pre-defined scan period.
handler.postDelayed(new Runnable() {
#Override
public void run() {
btAdapter.stopLeScan(leScanCallback);
progressBar.setVisibility(View.INVISIBLE);
}
}, SCAN_PERIOD);
btAdapter.startLeScan(leScanCallback);
progressBar.setVisibility(View.VISIBLE);
Log.i(getClass().getSimpleName(), "scanning bluetooth LE devices");
} else {
progressBar.setVisibility(View.INVISIBLE);
btAdapter.stopLeScan(leScanCallback);
}
}
// Device scan callback.
private BluetoothAdapter.LeScanCallback leScanCallback =
new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
runOnUiThread(new Runnable() {
#Override
public void run() {
addListItem(availableDevicesList, device);
}
});
}
};
#Override
public void onPause() {
scanLeDevice(false);
super.onPause();
}
private void addListItem(final LinearLayout list, final BluetoothDevice device) {
//only add devices with the right name
if (device == null ||
device.getName() == null ||
//name of prototype: RNDEF8
!device.getName().startsWith("RND")) {
return;
}
Log.i(getClass().getSimpleName(), "device: " + device.getName());
final View item = getLayoutInflater()
.inflate(R.layout.li_bluetooth_device, list, false);
((TextView)item.findViewById(android.R.id.text1)).setText(device.getName());
item.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
gatt = device.connectGatt(getApplicationContext(), false, gattCallback);
}
});
list.addView(item, 0);
}
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) {
services = gatt.getServices();
Log.i("onServicesDiscovered", services.toString());
}
#Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic
ch, int status) {
Log.i(getClass().getSimpleName(), ch.getPermissions() + "");
gatt.disconnect();
}
#Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
}
};
private static final UUID Read_UUID = UUID.fromString("00035b03-58e6-07dd-021a-08123a000300");
public void sendCommand(final byte[] value) {
BluetoothGattService service = gatt.getService(Read_UUID);
gattServer.addService(service);
BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID.fromString("00035b03-58e6-07dd-021a-08123a000301"));
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
characteristic.setValue(value);
gatt.setCharacteristicNotification(characteristic, true);
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
gatt.writeDescriptor(descriptor);
Log.i(getClass().getSimpleName(), "" + gatt.writeCharacteristic(characteristic));
}
public void sendSU(View view) {
Log.i(getClass().getSimpleName(), "clicked su");
sendCommand("\r".getBytes());
}
public void sendSL(View view) {
Log.i(getClass().getSimpleName(), "clicked sl");
sendCommand("SL".getBytes());
}
public void sendSP(View view) {
Log.i(getClass().getSimpleName(), "clicked sp");
sendCommand("SP".getBytes());
}
}
Thanks!