Android 中央与 GattServer

Android Central with GattServer

我正在尝试编写低功耗蓝牙 - AlertNotificationService (ANS)。这是一个有点奇怪的服务,因为通常在 GAP 外围设备上服务 运行。但是 ANS 运行 在 GAP 中央。所以典型的工作方式应该是这样的:

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

基本上它对我有用,但并非总是如此。这种不稳定对我来说很奇怪。当我使用蓝牙 LE 分析器查看时,我看到 Android GATT 服务器有时会告诉我的配置文件中没有特征...

它看起来像这样:"watch" 请求我的 GATT 服务(我知道它是专有的而不是 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 表示服务从句柄 0x35

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

手表从句柄 0x35 请求特征

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

但 phone 有时会错误地说该句柄没有特征:

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

当我向 GATT 服务器添加服务和特性时,我总是从函数中得到 "true"。我这样做:

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);

知道可能是什么问题吗?我注意到有函数 BluetoothGattServer::connect()。我不确定如何使用它。我使用的是标准 BluetoothDevice::connectGatt()。但我想如果我做错了什么,它永远不会奏效——有时不会…… 我在三星 SM-G920F 上使用 Android M (6.0.1)。

[更新]

我注意到 phone 重新启动后它总是有效。应用程序关闭并重新打开后,它通常不起作用。它不会以不同的方式工作 ->

当我启动 Gatt 服务器时,我是这样做的:

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

当我关闭应用程序时 (onDestroy()) 我会关闭 gattserver:

mGattServer.close();

我也试过不关闭GATT服务器,但没有用。有什么想法在关闭和重新打开之间可能会出错吗?

所以我可能找到原因了。我要添加 2 项服务:ANS 和我的服务 ANS_extension。当我在回调中添加服务后等待时似乎有帮助 onServiceAdded()

所以现在看起来像这样:

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);

然后我在 GATT 服务器回调中清除等待标志 waitServiceAdded。 (我是 java 新手,所以您可能想使用一些线程互斥同步来访问布尔值?)

private BluetoothGattServerCallback mGattServerCallback = new BluetoothGattServerCallback() {
@Override
  public void onServiceAdded (int status,
                                    BluetoothGattService service){
    waitServiceAdded = false;
  }