I'm trying to implement an app for transfer some strings between ble devices (for now one device act as central and the other one as pheripheral) but without success.
This is how my peripheral (server) is set up. Characteristic build
fun buildCharacteristic(
characteristicUUID: UUID,
): BluetoothGattCharacteristic {
var properties = BluetoothGattCharacteristic.PROPERTY_READ or
BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE or
BluetoothGattCharacteristic.PROPERTY_NOTIFY
var permission = BluetoothGattCharacteristic.PERMISSION_READ or
BluetoothGattCharacteristic.PERMISSION_WRITE
var characteristic = BluetoothGattCharacteristic(
characteristicUUID,
properties,
permission
)
return characteristic
}
service build
fun buildService(
serviceUUID: UUID,
serviceType: Int,
characteristics: List<BluetoothGattCharacteristic>
) {
bluetoothGattService = BluetoothGattService(
serviceUUID,
BluetoothGattService.SERVICE_TYPE_PRIMARY
)
for (characteristic in characteristics) {
bluetoothGattService.addCharacteristic(characteristic)
}
}
and this is how i start ble server (i omit implementation of callbacks)
fun startServer(
bleAdapter: BluetoothAdapter,
btManager: BluetoothManager,
context: Context
) {
bleAdvertiser = bleAdapter.bluetoothLeAdvertiser
bleGattServer = btManager.openGattServer(context, gattServerCallback)
bleGattServer.addService(bluetoothGattService)
var settings = AdvertiseSettings.Builder().apply {
setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY)
setConnectable(true)
setTimeout(0)
setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH)
}
var data = AdvertiseData.Builder().apply {
setIncludeDeviceName(true)
}
bleAdvertiser.startAdvertising(settings.build(), data.build(), advertiseCallback)
}
On central (client) side, when onScanResult is triggered, i try to connect with device:
fun connectToDevice(device: BluetoothDevice) {
device.connectGatt(
context,
false,
createGattCallback()
)
}
where createGattCallback() is a function return a BluetoothGattCallback object. Inside this callback, when onConnectionStateChange is called, i call service discover, and when service is discovered i try do write data to peripheral
override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
super.onServicesDiscovered(gatt, status)
if (gatt?.services != null) {
var serviceFound = false
for (service in gatt.services) {
if (service.uuid == Consts.SERVICE_UUID) {
serviceFound = true
var bluetoothGattCharacteristic = service.getCharacteristic(Consts.CHARACTERISTIC_UUID)
writeCharacteristic(
gatt,
bluetoothGattCharacteristic
)
}
}
if (!serviceFound) {
gatt.disconnect()
}
}
}
fun writeCharacteristic(
gatt: BluetoothGatt,
characteristic: BluetoothGattCharacteristic
) {
var toSendString = "A random string for testing purpose only"
var toSendByteArray = toSendString.toByteArray(Charsets.UTF_8)
val chunkSize = 18
val numberOfPackets = ceil(
(toSendByteArray.size).toDouble() / chunkSize.toDouble()
)
for (i in 0 until numberOfPackets.toInt()) {
var startIndex = i * chunkSize
var endIndex = if (startIndex + chunkSize <= toSendByteArray.size) {
startIndex + chunkSize
} else {
toSendByteArray.size
}
var packet = toSendByteArray.copyOfRange(startIndex, endIndex)
characteristic.value = packet
gatt.writeCharacteristic(characteristic)
Thread.sleep(250)
}
}
My code seems not workin, on peripheral i don't receive entire string, but only the first 18 bytes. Where i'm wrong?