1

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:

  1. Call mBtAdapter.setName("NEW_NAME")

  2. Method returns true (success)

  3. ACTION_LOCAL_NAME_CHANGED broadcast is fired

  4. Proceed with next steps

Observed Behavior on Some Devices:

  1. setName() returns true

  2. But 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:

  1. Is this a known Android Bluetooth stack issue? Has anyone else encountered this?

  2. Is there a better way to reliably detect when Bluetooth name change completes?

  3. 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!

1 Answer 1

1

Yeah, it’s a known issue on newer Android versions. Some OEMs don’t fire ACTION_LOCAL_NAME_CHANGED reliably anymore. Your timeout fallback is the best workaround — just avoid rapid name changes and keep the delay around 2–3 seconds. getName() is safe for checking once the adapter is stable.

Sign up to request clarification or add additional context in comments.

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.