Skip to content

[Android] Local name is not always updated during Scan #995

@murilommp

Description

@murilommp

Hello, everyone.

I'm building a cordova app for Android with the goal of write data to and read data from a proprietary BLE device. Everything works great, but I am facing an issue when scanning devices with "ble.startScan()" just after I have changed the device name. The new device name is not updated immediately.

My proprietary device is advertising it's name correctaly and I can receive the updated information when I use third party apps (like ST BLE TooBox) to perform an scan.

I realize that method asJSONObject() in Peripheral class (in file Peripheral.java) uses method getName() from class BluetoothDevice to fill attribute name in JSON object passed as parameter to javascript callback. I saw in method documentation that the name returned by it may be old due to have been extracted from cache.

I also checked that class ScanRecord has the method getDeviceName and it returns the local name received in advertising packet.
So I created an attribute called "advertsingName" in class Peripheral to hold that information:

private BluetoothDevice device;
private byte[] advertisingData;
private String advertsingName = null;
private int advertisingRSSI;
private boolean autoconnect = false;
private boolean connected = false;
private boolean connecting = false;
private ConcurrentLinkedQueue<BLECommand> commandQueue = new ConcurrentLinkedQueue<BLECommand>();
private final Map<Integer, L2CAPContext> l2capContexts = new HashMap<Integer, L2CAPContext>();
private final AtomicBoolean bleProcessing = new AtomicBoolean();

Then, I changed the constructor from:

public Peripheral(BluetoothDevice device, int advertisingRSSI, byte[] scanRecord) {
        this.device = device;
        this.advertisingRSSI = advertisingRSSI;
        this.advertisingData = scanRecord;
}

to

public Peripheral(BluetoothDevice device, int advertisingRSSI, byte[] scanRecord, String advertsingName) {
      this.device = device;
      this.advertisingRSSI = advertisingRSSI;
      this.advertisingData = scanRecord;
      this.advertsingName = advertsingName;
}

And finally, I changed method asJSONObject from:

public JSONObject asJSONObject()  {

	JSONObject json = new JSONObject();

	try {
		json.put("name", device.getName());
		json.put("id", device.getAddress()); // mac address
		if (advertisingData != null) {
			json.put("advertising", byteArrayToJSON(advertisingData));
		}
		// TODO real RSSI if we have it, else
		if (advertisingRSSI != FAKE_PERIPHERAL_RSSI) {
			json.put("rssi", advertisingRSSI);
		}
	} catch (JSONException e) { // this shouldn't happen
		e.printStackTrace();
	}

	return json;
}

to

public JSONObject asJSONObject()  {

	JSONObject json = new JSONObject();

	try {
		if(this.advertsingName == null)
			json.put("name", device.getName());
		else
			json.put("name", this.advertsingName);

		json.put("id", device.getAddress()); // mac address
		if (advertisingData != null) {
			json.put("advertising", byteArrayToJSON(advertisingData));
		}
		// TODO real RSSI if we have it, else
		if (advertisingRSSI != FAKE_PERIPHERAL_RSSI) {
			json.put("rssi", advertisingRSSI);
		}
	} catch (JSONException e) { // this shouldn't happen
		e.printStackTrace();
	}

	return json;
}

I also changed the onScanResult() in BLECentralPlugin.java file from:

public void onScanResult(int callbackType, ScanResult result) {
	LOG.w(TAG, "Scan Result");
	super.onScanResult(callbackType, result);
	BluetoothDevice device = result.getDevice();
	String address = device.getAddress();
	boolean alreadyReported = peripherals.containsKey(address) && !peripherals.get(address).isUnscanned();

	if (!alreadyReported) {

		Peripheral peripheral = new Peripheral(device, result.getRssi(), result.getScanRecord().getBytes());
		peripherals.put(device.getAddress(), peripheral);

		if (discoverCallback != null) {
			PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, peripheral.asJSONObject());
			pluginResult.setKeepCallback(true);
			discoverCallback.sendPluginResult(pluginResult);
		}

	} else {
		Peripheral peripheral = peripherals.get(address);
		if (peripheral != null) {
			peripheral.update(result.getRssi(), result.getScanRecord().getBytes());
			if (reportDuplicates && discoverCallback != null) {
				PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, peripheral.asJSONObject());
				pluginResult.setKeepCallback(true);
				discoverCallback.sendPluginResult(pluginResult);
			}
		}
	}
}

to

public void onScanResult(int callbackType, ScanResult result) {
	LOG.w(TAG, "Scan Result");
	super.onScanResult(callbackType, result);
	BluetoothDevice device = result.getDevice();
	String address = device.getAddress();
	boolean alreadyReported = peripherals.containsKey(address) && !peripherals.get(address).isUnscanned();

	if (!alreadyReported) {

		Peripheral peripheral = new Peripheral(device, result.getRssi(), result.getScanRecord().getBytes(), result.getScanRecord().getDeviceName());
		peripherals.put(device.getAddress(), peripheral);

		if (discoverCallback != null) {
			PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, peripheral.asJSONObject());
			pluginResult.setKeepCallback(true);
			discoverCallback.sendPluginResult(pluginResult);
		}

	} else {
		Peripheral peripheral = peripherals.get(address);
		if (peripheral != null) {
			peripheral.update(result.getRssi(), result.getScanRecord().getBytes());
			if (reportDuplicates && discoverCallback != null) {
				PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, peripheral.asJSONObject());
				pluginResult.setKeepCallback(true);
				discoverCallback.sendPluginResult(pluginResult);
			}
		}
	}
}

Now I always have the local name updated during scan, even just after I have writen a new value to it.

Is there any other way to have the local name updated during scan instead having a cached info?

Thanks in advance!

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions