Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
Here my
BluetoothGattServerCallback
where I handle two events
STATE_CONNECTED
and
STATE_DISCONNECTED
private static class CallBack extends BluetoothGattServerCallback {
private Set<BluetoothDevice> mRegisteredDevices = new HashSet<>();
private MainActivity mMainActivity;
public CallBack(Set<BluetoothDevice> registeredDevices, MainActivity mainActivity){
mRegisteredDevices = registeredDevices;
mMainActivity = mainActivity;
@Override
public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
Log.i(TAG,"onConnectionStateChange()");
switch (newState)
case STATE_CONNECTED :
handleStateConnected( device, status, newState);
break;
case STATE_DISCONNECTED :
handleStateDisconnected( device, status, newState);
break;
Here is handler STATE_CONNECTED
private void handleStateConnected(BluetoothDevice device, int status, int newState)
Log.i(TAG, "BluetoothDevice CONNECTED: " + device);
mRegisteredDevices.add(device);
stopAdvertising();
Here is handler STATE_DISCONNECTED
private void handleStateDisconnected(BluetoothDevice device, int status, int newState)
Log.i(TAG, "BluetoothDevice DISCONNECTED: " + device);
mRegisteredDevices.remove(device);
startAdvertising();
On STATE_CONNECTED
I would like my phone to stop advertising, and on STATE_DISCONNECTED
I would like the phone to resume advertising; the default behaviour appears to be that the device will continue advertising after it's connected, so I added stopAdvertising()
and startAdvertising()
in the event handlers handleStateConnected()
and handleStateDisconnected()
respectively.
The phone now goes into an ifinite loop of connecting and recconnecting, the reason being that after calling stopAdvertising()
the phone will disconnect, causing it to begin advertising again, after which it will connect.
The control flow of my app is to begin advertising, then set up GATT server:
private void initServer(){
Log.v(TAG,"initServer()");
mBluetoothManager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
BluetoothAdapter bluetoothAdapter = mBluetoothManager.getAdapter();
// We can't continue without proper Bluetooth support
if (!checkBluetoothSupport(bluetoothAdapter)) {
finish();
// Register for system Bluetooth events (GATT server started in receiver)
IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
registerReceiver(mBluetoothReceiver, filter);
if (!bluetoothAdapter.isEnabled()) {
Log.d(TAG, "Bluetooth is currently disabled...enabling");
bluetoothAdapter.enable();
} else {
startAdvertising();
startServer();
Here is startAdvertising()
public static void startAdvertising() {
Log.i(TAG,"startAdvertising()");
BluetoothAdapter bluetoothAdapter = mBluetoothManager.getAdapter();
mBluetoothLeAdvertiser = bluetoothAdapter.getBluetoothLeAdvertiser();
if (mBluetoothLeAdvertiser == null) {
Log.w(TAG, "Failed to create mBleAdvertiser");
return;
Log.v(TAG,"created advertizer");
AdvertiseSettings settings = new AdvertiseSettings.Builder()
.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_BALANCED)
.setConnectable(true)
.setTimeout(0) // Limit advertising to a given amount of time A value of 0 will disable the time limit
.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM)
.build();
boolean isNameChanged = BluetoothAdapter.getDefaultAdapter().setName(DEVICE_NAME);
if(isNameChanged) Log.d(TAG,"Device name changed successfully.");
AdvertiseData data = new AdvertiseData.Builder()
.setIncludeDeviceName(true)
.setIncludeTxPowerLevel(false)
.addServiceUuid(ParcelUuid.fromString(Services.GloService.UUID))
.build();
mBluetoothLeAdvertiser
.startAdvertising(settings, data, mAdvertiseCallback);
Here is startServer()
private void startServer() {
Log.i(TAG,"startServer()");
mBluetoothGattServer =
MyProfile.getOpenServer(this, mBluetoothManager,mRegisteredDevices,this);
if (mBluetoothGattServer == null) {
Log.w(TAG, "Unable to create GATT server");
return;
And here is MyProfile.getOpenServer
which returns the server object initialized with the call back declared at the top of the post.
public static BluetoothGattServer getOpenServer(Context ctx,
BluetoothManager bluManager,
Set<BluetoothDevice> registeredDevices,
MainActivity mainActivity){
mBluetoothManager = bluManager;
CallBack callBack = new CallBack(registeredDevices, mainActivity);
BluetoothGattServer server = bluManager.openGattServer(ctx, callBack);
BluetoothGattService myService = getMyService();
server.addService(myService);
return server;
–
–
Here's one thing I have done in the past that helps with this problem. No guarantees, but it's the best workaround I've found.
When you get a STATE_CONNECTED event on the server side, call BluetoothGattServer.connect(BluetoothDevice, boolean). Here is a snippet that I've used before.
@Override
public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
switch (newState) {
case BluetoothProfile.STATE_CONNECTED:
gattServer.connect(device, false); // prevents disconnection when advertising stops
// stop advertising here or whatever else you need to do
break;
–
–
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.