Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Peripheral Name is sometimes null #669

Open
dominikkv opened this issue Apr 18, 2024 · 2 comments
Open

Peripheral Name is sometimes null #669

dominikkv opened this issue Apr 18, 2024 · 2 comments

Comments

@dominikkv
Copy link

Hi,

on an Android device, I scan for BT devices with a service & name prefix filter. When an advertisement is received, I create a peripheral. In very rare occasions, the name of the peripheral is null, despite the name of the advertisement I used to create the peripheral was not null!

I am always testing with the same device, same identifier. When the name is null, the peripheral is still "usable", meaning I can connect and use it as usual.

private val scanner = Scanner {
    filters = listOf(
        Filter.Service(SERVICE_DEVICE_INFORMATION),
        Filter.NamePrefix("MYPREFIX-"),
    )
}
private val scannerFlow = scanner.advertisements

// ===========

scannerFlow.catch { e ->
    log.e(e, "BTLog") { "Error while scanning" }
}.onCompletion {
    log.d("BTLog") { "BT scan deactivated." }
}.collect { advertisement ->
    log.d("BTLog") { "Advertisement: ${advertisement.name} - ${advertisement.identifier}" } // name not null
    val peripheral = scope.peripheral(advertisement) { }
    log.d("BTLog") { "Peripheral: ${peripheral.name} - ${peripheral.identifier}" } // name sometimes null
}
@kevinskrei
Copy link

It appears to me that the above is correct on Android. Pixel 9 Pro - Android 15. This happens frequently when reconnecting a device that has previously disconnected.

@twyatt
Copy link
Member

twyatt commented Jan 21, 2025

Sadly, this seems to be a limitation of Android. Looks like the name may be cleared under some conditions, including: if BLE is turned off, or if BLE cache has recently been cleared.

The Android implementation (that Kable calls into) looks like:

/**
 * Get the friendly Bluetooth name of the remote device.
 *
 * <p>The local adapter will automatically retrieve remote names when
 * performing a device scan, and will cache them. This method just returns
 * the name for this device from the cache.
 *
 * @return the Bluetooth name, or null if there was a problem.
 */
public String getName() {
    if (DBG) log("getName()");
    final IBluetooth service = getService();
    final String defaultValue = null;
    if (service == null || !isBluetoothEnabled()) {
        Log.e(TAG, "BT not enabled. Cannot get Remote Device name");
        if (DBG) log(Log.getStackTraceString(new Throwable()));
    } else {
        try {
            final SynchronousResultReceiver<String> recv = SynchronousResultReceiver.get();
            service.getRemoteName(this, mAttributionSource, recv);
            String name = recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
            if (name != null) {
                // remove whitespace characters from the name
                return name
                    .replace('\t', ' ')
                    .replace('\n', ' ')
                    .replace('\r', ' ');
            }
        } catch (RemoteException | TimeoutException e) {
            Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
        }
    }
    return defaultValue;
}

Perhaps it would make sense for Kable to do its own caching of the name and be more conservative about clearing its value?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants