Android BLE advertiser transmits residual data even though stop advertising method is called

Viewed 45

I can stop advertising if the app is in the foreground and I call the advertiser.stopAdvertising() method. The problem occurs when my screen turn off.

I have two devices, an Android that sends data with the BLE advertiser and a device that is listening. I target the API 21, to change the data sent by the advertiser, I stop the advertiser and then restart it with new data. For safety, an Handler stop advertiser on its own after a while.

public class BluetoothManager extends Application
{
    private static BluetoothManager Instance;

    private BluetoothAdapter adapter;
    private android.bluetooth.BluetoothManager manager;

    private AdvertiseCallback AdvertiseCallbackCalibration = new AdvertiseCallback(){};
    private Handler handlerCalibration= new Handler();
    private BluetoothLeAdvertiser BLEAdvertiserCalibration;

    public static BluetoothManager getApplication()
    {
        return Instance;
    }

    public void onCreate()
    {
        super.onCreate();

        EnableBluetooth();
        Instance = this;
    }

    void CreateBLEAdvertiser()
    {
        if (adapter == null)
        {
            manager = (android.bluetooth.BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
            adapter = manager.getAdapter();
        }

        if (adapter.isMultipleAdvertisementSupported() && adapter.isEnabled())
        {
            if(BLEAdvertiserCalibration == null)
            {
                BLEAdvertiserCalibration = adapter.getBluetoothLeAdvertiser();
            }
        }
        else
        {
            EnableBluetooth();
        }
    }

    void SendData(byte[] data)
    {
        if (adapter.isEnabled())
        {
            AdvertiseSettings settings = new AdvertiseSettings.Builder().setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY).setConnectable(false).setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH).build();
            AdvertiseData data = new AdvertiseData.Builder().addManufacturerData(2200, data).build();

            if(BLEAdvertiserCalibration != null)
            {
                BLEAdvertiserCalibration.stopAdvertising(AdvertiseCallbackCalibration);
                handlerCalibration.removeCallbacksAndMessages(null);
            }

            BLEAdvertiserCalibration.startAdvertising(settings, data, AdvertiseCallbackCalibration);
            handlerCalibration.postDelayed(() -> BLEAdvertiserCalibration.stopAdvertising(AdvertiseCallbackCalibration), 3000);
        }
        else
        {
            EnableBluetooth();
        }
    }

    private void EnableBluetooth()
    {
        Intent intentBluetooth = new Intent();
        intentBluetooth.setAction(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        this.startActivity(intentBluetooth);
    }
}

This class is a Singleton which extends Application because multiple Activity can send data. This allows to ensure that is the same advertiser and callback there are called and stopped regardless of the context.

It works as expected. During input, the Android sends the data and the second device receives it. The transmission stops either by itself or manually, Android no longer transmits data and the second device no longer receives it.

Problem: after several uses, if the phone screen turns off by itself (this does not happen if the user manually turn off her screen) datas are received by the second device while the Android does not call SendData(). Of course, no data is intentionally being sent when the screen turns off. Datas received correspond to that previously transmitted, but in a somewhat random order.

Any idea? It's like if the bluetooth chip purge residual data...

EDIT

An example of data sent by Android. I'm sure that the data received by the second device comes from the Android, because the byte array received match.

static byte[] Calibration(byte statut)
{
    byte[] packet = new byte[3];
    try
    {
        byte[] buffer;
        int i, size, limit;
        i = 0;

        // Type bluetooth packet
        size = 2;
        limit = i + size;// char
        buffer = ByteBuffer.allocate(size).putChar('C').array();
        for (int j = size - 1; i < limit; i++, j--)
        {
            packet[i] = buffer[j];
        }

        // State
        size = 1;
        limit = i + size;// bool
        buffer = ByteBuffer.allocate(size).put(statut).array();
        for (int j = size - 1; i < limit; i++, j--)
        {
            packet[i] = buffer[j];
        }
    }
    catch (NumberFormatException e)
    {
        packet = new byte[3];
    }
    return packet;
}
0 Answers
Related