0

I'm trying to program Bluetooth low energy - AlertNotificationService (ANS). It is a bit weird service because typically services run on GAP peripheral. But ANS run on GAP central. So typical way of working shall be for example this:

Watch - GAP peripheral (broadcasting), GATT client
Phone - GAP central                  , GATT server

Basically it works for me but not always. And this instability is very strange to me. When I look with bluetooth LE analyzer I see that Android GATT server sometimes tells there are no characteristic in my profile...

It looks like this: "watch" ask for my GATT service (I know it is proprietary not ANS UUID)

Slave->Master ATT Rcvd Find By Type Value Request, GATT Primary Service Declaration 11:22:33:44:11:22:33:44:11:76:62:65:01:00:00:00

Phone says the service is there starting from handle 0x35

Master->Slave ATT Rcvd Find By Type Value Response Handle: 0x0035

Watch ask for charactersitisc from handle 0x35

Slave->Master ATT Rcvd Read By Type Request, GATT Characteristic Declaration, Handles: 0x0035..0xffff

But phone sometimes incorrectly says that there is no characteristic from that handle:

Master->Slave ATT Rcvd Error Response - Attribute Not Found, Handle: 0x0035

When I do add service and characteristic into GATT server I always get "true" from functions. I do it like this:

BluetoothGattService service =new BluetoothGattService(Vbe_AnsExt.UUID_SERVICE,
        BluetoothGattService.SERVICE_TYPE_PRIMARY);

BluetoothGattCharacteristic characApp =
        new BluetoothGattCharacteristic(Vbe_AnsExt.UUID_CharacApp,
                BluetoothGattCharacteristic.PROPERTY_READ ,
                BluetoothGattCharacteristic.PERMISSION_READ);

BluetoothGattCharacteristic characMsg =
        new BluetoothGattCharacteristic(Vbe_AnsExt.UUID_CharacMsg,
                BluetoothGattCharacteristic.PROPERTY_READ ,
                BluetoothGattCharacteristic.PERMISSION_READ );

boolean ret;
ret = service.addCharacteristic(characApp);
Log.i("vbeInit_ASN_Ext_Server","addCharApp  retruned: "+ret);
ret = service.addCharacteristic(characMsg);
Log.i("vbeInit_ASN_Ext_Server","addCharMsg  retruned: "+ret);

ret = mGattServer.addService(service);
Log.i("vbeInit_ASN_Ext_Server","addService  retruned: "+ret);

Any idea what might be the problem? I noticed that there is function BluetoothGattServer::connect(). I'm not sure how to use it. I'm using standard BluetoothDevice::connectGatt(). But I guess if I would do something wrong it shall work never - not sometimes... I'm using Android M (6.0.1) on Samsung SM-G920F.

[UPDATE]

I noticed that after phone restart it always works. After application close and reopen it usually does not works. It does not works in different ways ->

  • sometimes no characteristic is found;
  • sometimes only first characteristic is found
  • sometimes only last(second) characteristic is found.

When I start Gatt Server I do it like this:

mGattServer = bluetoothManager.openGattServer(appContext, mGattServerCallback);
mGattServer.clearServices();

When I close app (onDestroy()) I do close gattserver:

mGattServer.close();

I also tried not to close the GATT server, but it did not help. Any ideas what might get wrong between closing and reopening?

Vit Bernatik
  • 3,566
  • 2
  • 34
  • 40

1 Answers1

0

So I may have found the reason. I'm adding 2 services: ANS and my service ANS_extension. It seems it helps when I wait after adding the service on call back onServiceAdded()

So now it looks like this:

public static UUID UUID_SupportedNewAlertCategory     = UUID.fromString("00002a47-0000-1000-8000-00805f9b34fb");
public static UUID UUID_NewAlert                      = UUID.fromString("00002a46-0000-1000-8000-00805f9b34fb");
// descriptor used for enabling notify feature
public static UUID UUID_Descr_new                     = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
mGattServer = bluetoothManager.openGattServer(appContext, mGattServerCallback);
mGattServer.clearServices();
waitServiceAdded = true;
BluetoothGattService service = new BluetoothGattService(Vbe_Ans.UUID_SERVICE,
                BluetoothGattService.SERVICE_TYPE_PRIMARY);

BluetoothGattCharacteristic characSupportedNewAlerCategory =
                new BluetoothGattCharacteristic(Vbe_Ans.UUID_SupportedNewAlertCategory,
                        BluetoothGattCharacteristic.PROPERTY_READ ,
                        BluetoothGattCharacteristic.PERMISSION_READ);
BluetoothGattCharacteristic characNewAlert =
                new BluetoothGattCharacteristic(Vbe_Ans.UUID_NewAlert,
                        BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_NOTIFY,
                        BluetoothGattCharacteristic.PERMISSION_READ );
BluetoothGattDescriptor bgd = new BluetoothGattDescriptor(UUID_Descr_new,
                BluetoothGattDescriptor.PERMISSION_READ | BluetoothGattDescriptor.PERMISSION_WRITE);

characNewAlert.addDescriptor(bgd);
...
ret = service.addCharacteristic(characSupportedNewAlerCategory);
ret = service.addCharacteristic(characNewAlert);
...
ret = mGattServer.addService(service);
while(waitServiceAdded);

waitServiceAdded = true;
//init second service similar way as previous
while(waitServiceAdded);

Then I clear waiting flag waitServiceAdded in GATT server call back. (I'm java newbie so you might want to use some thread mutex synchro to access boolean?)

private BluetoothGattServerCallback mGattServerCallback = new BluetoothGattServerCallback() {
@Override
  public void onServiceAdded (int status,
                                    BluetoothGattService service){
    waitServiceAdded = false;
  }
Vit Bernatik
  • 3,566
  • 2
  • 34
  • 40