I'm working on an Android app that programmatically changes the Bluetooth device name using BluetoothAdapter.setName(). The app needs to know when the name change completes to trigger subsequent actions (starting BLE advertising).
Expected Behavior:
Call mBtAdapter.setName("NEW_NAME")
Method returns
true(success)ACTION_LOCAL_NAME_CHANGED broadcast is fired
Proceed with next steps
Observed Behavior on Some Devices:
setName() returns
trueBut ACTION_LOCAL_NAME_CHANGED broadcast is NEVER fired
Affected Devices/Scenarios:
Observed on OnePlus Nord 4 and several other devices
Seems to occur more frequently on Android 10+ devices
May be related to rapid consecutive name changes
Possibly related to Android's Bluetooth privacy enhancements
**Current Workaround/Solution:
I've implemented a hybrid approach that combines broadcast listening with a fallback timeout mechanism:**
// 1. Store expected name and set timeout handler
mExpectedBTName = name;
boolean success = mBtAdapter.setName(name);
if (!success) {
// Immediate failure - handle it
sendEvent(EVENT_BT_ADVERTISING_FAILED, null);
return;
}
// 2. Set fallback timeout (3 seconds)
mNameChangeTimeoutHandler = new Handler(Looper.getMainLooper());
mNameChangeTimeoutHandler.postDelayed(new Runnable() {
@Override
public void run() {
String updatedName = mBtAdapter.getName();
if (name.equalsIgnoreCase(updatedName)) {
// Name was changed, broadcast just didn't fire
startAdvertising();
} else {
// Name change actually failed
sendEvent(EVENT_BT_ADVERTISING_FAILED, null);
}
mNameChangeTimeoutHandler = null;
}
}, 3000);
// 3. Broadcast receiver
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equalsIgnoreCase(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED)) {
// Cancel timeout if broadcast is received
if (mNameChangeTimeoutHandler != null) {
mNameChangeTimeoutHandler.removeCallbacksAndMessages(null);
mNameChangeTimeoutHandler = null;
}
String currentBTName = intent.getExtras().getString(BluetoothAdapter.EXTRA_LOCAL_NAME);
if (mExpectedBTName != null && currentBTName.equalsIgnoreCase(mExpectedBTName)) {
mExpectedBTName = null;
startAdvertising();
}
}
}
Questions:
Is this a known Android Bluetooth stack issue? Has anyone else encountered this?
Is there a better way to reliably detect when Bluetooth name change completes?
Are there any risks with the fallback polling approach? Could checking getName() be unreliable in certain states?
Environment:
Min SDK: 24
Target SDK: 33
React Native app with native Bluetooth module
Using BLUETOOTH_CONNECT, BLUETOOTH_SCAN, BLUETOOTH_ADVERTISE permissions
Any insights or alternative approaches would be greatly appreciated!