I am sending an image from an Android app to an iOS app over BLE. According to some articles, the max size for sending via BLE is 1 KB, hence I am splitting my image into 1 KB chunks and sending it to the Swift App with a 40ms delay.
However, the chunk size seems to be too big. After debugging, I noticed that the characteristic's value that I am reading from within Swift can only be up to 187 bytes. Hence, when I am reducing my chunk size in Android to that number or smaller, the transfer succeeds, otherwise it does not since the data is cut off.
Does anybody know why it is limited to that size although it should rather be 1 KB? Or, if configurable how I can increase the size?
Here's my Android code:
private void writeImageToCharacteristic() {
// determine number of chunks and checksum
final int chunkSize = 1000; // fails with 1000, succeeds with 180
int numberOfChunks = imageInByte.length / chunkSize;
numberOfChunks = imageInByte.length == numberOfChunks * chunkSize ? numberOfChunks : numberOfChunks + 1;
// get the characteristic
BluetoothGattCharacteristic imgCharacteristic = mBluetoothGattServer
.getService(SERVICE_UUID)
.getCharacteristic(IMAGE_CHARACTERISTIC_UUID);
Log.d(TAG, "Image size in byte: " + imageInByte.length);
Log.d(TAG, "Number of chunks: " + numberOfChunks);
Log.d(TAG, "Start sending...");
updateStateLabel("State: sending image data...");
// first message contains information about the image
final String msg = String.valueOf(numberOfChunks);
imgCharacteristic.setValue(msg.getBytes());
mBluetoothGattServer.notifyCharacteristicChanged(mConnectedDevice, imgCharacteristic, false);
// create the chunks (and checksums if configured)
List<byte[]> messages = new ArrayList<>();
for(int i = 0; i < numberOfChunks; ++i) {
final int start = i * chunkSize;
final int end = start + chunkSize > imageInByte.length ? imageInByte.length : start + chunkSize;
final byte[] chunk = Arrays.copyOfRange(imageInByte, start, end);
messages.add(chunk);
if(includeChecksums) {
final String chunkCheckSum = calculateCheckSum(chunk);
messages.add(chunkCheckSum.getBytes());
}
}
// send the data to the device by writing
// it to the characteristic with a delay of 40 ms
for(byte[] aMsg : messages) {
SystemClock.sleep(40);
imgCharacteristic.setValue(aMsg);
mBluetoothGattServer.notifyCharacteristicChanged(mConnectedDevice, imgCharacteristic, false);
}
Log.d(TAG, "Finished sending");
updateStateLabel("State: finished sending.");
}
And here is the Swift code that reads it:
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
switch characteristic.uuid {
case Constants.ImageCharacteristicUUID:
let imgData = characteristic.value!
// here, the characteristic.value seems to be limited to 187 bytes - why?
processImageData(data: imgData!)
default:
print("Unhandled Characteristic UUID: \(characteristic.uuid)")
}
}
Appreciating any help.