Search code examples
javaandroidbluetooth-lowenergyrssi

How to update RSSI of Device in List of BLE Beacons


I want to update the RSSI value of each beacon. However I do not seem to get it working. I want to use Map or HashMap in order to update the RSSI of the device holder:

private Map<BluetoothDevice, Integer> mDevicesRssi;

This is my device Holder class:

class DeviceHolder{
    BluetoothDevice device;
    int rssi;
    public DeviceHolder(BluetoothDevice device, int rssi){
        this. device = device;
        this.rssi = rssi;
    }
}

and my adapter class

private class LeDeviceListAdapter extends BaseAdapter {
    private ArrayList<BluetoothDevice> mLeDevices;
    private ArrayList<DeviceHolder> mLeHolders;
    private LayoutInflater mInflator;

    public LeDeviceListAdapter() {
        super();
        mLeDevices = new ArrayList<BluetoothDevice>();
        mLeHolders = new ArrayList<DeviceHolder>();
        mInflator = DeviceScanActivity.this.getLayoutInflater();
    }

    public void addDevice(DeviceHolder deviceHolder) {
       if(!mLeDevices.contains(deviceHolder.device)) {
            DeviceHolder actualDeviceHolder = new DeviceHolder
            mLeDevices.add(deviceHolder.device);
            mLeHolders.add(deviceHolder);
       }
       else {
            mDevicesRssi.put(deviceHolder.device, deviceHolder.rssi);
       }
       mLeDeviceListAdapter.notifyDataSetChanged();
    }

I think I have to create an Array like in the LeDeviceListAdapter class such as:

mDevicesRssi = new Map<BluetoothDevice, Integer>();

However this gives me the error that Map is abstract. My question is: does anyone have a hint on how to update the rssi of the deviceHolder object so that the RSSI is updated in the List that is displayed in the App?

Everything else seems to be working fine. When I just add the devices without the if condition, the app lists a new device for each advertisement --> no filter.

Thanks a lot

Sayus


Solution

  • I was able to find the solution by myself. If anyone encounters the same issue when using the somewhat outdated BluetoothLeGatt Example provided by google I hope this answer helps him:

    import java.util.HashMap;
    
    public class DeviceHolder{
        private BluetoothDevice device;
        private int rssi;
    
    
        public DeviceHolder(BluetoothDevice device, int rssi){
            this. device = device;
            this.rssi = rssi;
        }
        public String getAddress() {
            return device.getAddress();
        }
        public String getName() {
            return device.getName();
        }
        public void setRSSI(int rssi){
            this.rssi = rssi;
        }
        public int getRSSI() {
            return rssi;
        }
    }
    
    private class LeDeviceListAdapter extends BaseAdapter {
        private ArrayList<BluetoothDevice> mLeDevices;
        private ArrayList<DeviceHolder> mLeHolders;
        private LayoutInflater mInflator;
        private HashMap<String, DeviceHolder> mLeDevicesRssi;
    
        public LeDeviceListAdapter() {
            super();
            mLeDevices = new ArrayList<BluetoothDevice>();
            mLeHolders = new ArrayList<DeviceHolder>();
            mLeDevicesRssi = new HashMap<String, DeviceHolder>();
            mInflator = DeviceScanActivity.this.getLayoutInflater();
        }
    
        public void addDevice(DeviceHolder deviceHolder, int rssi) {
            String address = deviceHolder.device.getAddress();
           if(!mLeDevices.contains(deviceHolder.device)) {
               DeviceHolder cDeviceHolder = new DeviceHolder(deviceHolder.device, deviceHolder.rssi);
               cDeviceHolder.setRSSI(rssi);
               mLeDevicesRssi.put(address, cDeviceHolder);
               mLeDevices.add(cDeviceHolder.device);
               mLeHolders.add(cDeviceHolder);
           }
           else if(mLeDevices.contains(deviceHolder.device)) {
               mLeDevicesRssi.get(address).setRSSI(rssi);
           }
           mLeDeviceListAdapter.notifyDataSetChanged();
        }
    ....
    }
    
     private BluetoothAdapter.LeScanCallback mLeScanCallback =
            new BluetoothAdapter.LeScanCallback() {
    
                @Override
                public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
                    DeviceHolder deviceHolder = new DeviceHolder(device, rssi);
                    final int new_rssi = rssi;
                    runOnUiThread(new DeviceAddTask( deviceHolder, new_rssi ) );
                }
            };
    
    class DeviceAddTask implements Runnable {
        DeviceHolder deviceHolder;
    
        public DeviceAddTask( DeviceHolder deviceHolder, int rssi ) {
            this.deviceHolder = deviceHolder;
            this.deviceHolder.rssi = rssi;
        }
    
        public void run() {
            mLeDeviceListAdapter.addDevice(deviceHolder, deviceHolder.rssi);
            mLeDeviceListAdapter.notifyDataSetChanged();
        }
    }
    

    it may not be the most efficient way to display the RSSI in a continous fashion. But it does work.