8

I am trying to send more than 33 bytes using simple loops, Is anybody has idea how to send more than 20 bytes data over android ble.

if(!mConnected) return;
        for (int i = 0; i<str.length;i++) {
            if(str[i] == str[str.length -1]){
                 val = str[i]+"\n";
            }else {
                val = str[i] + "_";
            }
            System.out.println(val);
            mBluetoothLeService.WriteValue(val);
        }
Nik
  • 123
  • 1
  • 1
  • 11
  • Is the destination of the data also an Android device? – ThomasW May 28 '15 at 04:53
  • No It is custom BLE peripheral. – Nik May 28 '15 at 14:52
  • OK. In my tests Android will send over 20 bytes to an iOS peripheral, so perhaps it depends on the type of the peripheral. However, by default it will only receive 20 bytes from a iOS peripheral. – ThomasW May 29 '15 at 01:28

4 Answers4

8

Sending more than 20 bytes via BLE is easily achievable by splitting your data into 20 byte packets and implementing a short delay (i.e. using sleep()) between sending each packet.

Here's a short snippet of code from a project I'm working on that takes data in the form of byte[] and splits it into an array of the same, ( byte[][] ), in 20 byte chunks, and then sends it to another method that transmits each packet one by one.

    int chunksize = 20;
    byte[][] packets = new byte[packetsToSend][chunksize]; 
    int packetsToSend = (int) Math.ceil( byteCount / chunksize);

    for(int i = 0; i < packets.length; i++) {
        packets[i] = Arrays.copyOfRange(source,start, start + chunksize);
        start += chunksize;
    }

    sendSplitPackets(packets);

Here are two other very good explanations of how to achieve this:

(Stackoverflow) Android: Sending data >20 bytes by BLE

(Nordic Semi) Dealing Large Data Packets Through BLE

Community
  • 1
  • 1
Brock Amhurst
  • 497
  • 2
  • 5
  • i have to send data repeatedly once the activity is launch. if there is change or no change but I have to send it. so Sometimes my data got overlapped to each other nd ruin my functionality. – Nik May 11 '15 at 15:09
  • 1
    I don't fully understand the problem you're having, but what I would recommend is to ensure that (1) you're implementing a short delay between packets and (2) send an initial "header" packet that tells your method how many total packets to expect, and use an incrementing counter to ensure the correct number was received. If you can explain your use case a little more I can perhaps help with more detailed suggestions – Brock Amhurst May 11 '15 at 21:23
  • Do you have any idea how to maintain established bluetooth connection in whole android app.. Right now i am establish new connection in every activity of app. – Nik May 20 '15 at 20:17
  • I get timedout error if i send multiple chunks of 20. I have max 30-35 bytes to send. Please help. – moDev Sep 02 '19 at 15:36
6

You can send more than 20 bytes of data without breaking into chunks and including a delay. Every characteristics you are trying to write has an MTU value assigned. It's number of bytes you can write in one time. During the connection MTU values are exchanged and you can write those many bytes at a time. You can increase the mtu value on the server side (Max 512 bytes) and send that much bytes in one go.

For Android, you might want to request mtu manually after connecting with the server using

requestMtu(int mtu)

This is return true or false based on the mtu value you send. It will give a callback to onMtuChanged where Android device and server negotiate the maximum possible MTU value.

onMtuChanged (BluetoothGatt gatt, int mtu, int status)

and you can set MTU value in this function and can send more than 20 bytes in one go.

HelloWorld
  • 61
  • 1
  • 5
1

Some embedded bluetooth LE implementations limit the size of a characteristic to be 20 bytes. I know that the Laird BL600 series does this. This is limitation of the Laird module, even though the BLE spec calls for the max length to be longer. Other embedded BLE solutions have similar limits. I suspect this is the limitation that you are encountering.

Rob Gorman
  • 3,502
  • 5
  • 28
  • 45
1

Instead of using sleep for every chunk, i just found a better and efficient way for my application to send more than 20 bit data.

The packets will be send after onCharacteristicWrite() triggered. i just found out this method will be triggered automatically after peripheral device (BluetoothGattServer) sends a sendResponse() method.

firstly we have to transform the packet data into chunk with this function:

public void sendData(byte [] data){
    int chunksize = 20; //20 byte chunk
    packetSize = (int) Math.ceil( data.length / (double)chunksize); //make this variable public so we can access it on the other function

    //this is use as header, so peripheral device know ho much packet will be received.
    characteristicData.setValue(packetSize.toString().getBytes());
    mGatt.writeCharacteristic(characteristicData);
    mGatt.executeReliableWrite();

    packets = new byte[packetSize][chunksize];
    packetInteration =0;
    Integer start = 0;
    for(int i = 0; i < packets.length; i++) {
        int end = start+chunksize;
        if(end>data.length){end = data.length;}
        packets[i] = Arrays.copyOfRange(data,start, end);
        start += chunksize;
    }

after our data ready, so i put my iteration on this function:

@Override
    public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
        if(packetInteration<packetSize){
        characteristicData.setValue(packets[packetInteration]);
        mGatt.writeCharacteristic(characteristicData);
            packetInteration++;
        }
    }
Doni
  • 576
  • 6
  • 9