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;
}
我正在尝试编写低功耗蓝牙 - 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;
}