大家可以先看一下starkoverflow的一个讨论(时间是两年前的):
http://stackoverflow.com/questions/17910322/android-ble-api-gatt-notification-not-received
大致内容就是安卓上的app明显调用了
public boolean setCharacteristicNotification (BluetoothGattCharacteristic characteristic, boolean enable)
的接口,却收不到gatt server发过来的notification。
让我们先看看这个接口的解释:
Enable or disable notifications/indications for a given characteristic.
Once notifications are enabled for a characteristic, a onCharacteristicChanged(BluetoothGatt, BluetoothGattCharacteristic) callback will be triggered if the remote device indicates that the given characteristic has changed.
Requires BLUETOOTH permission.
Parameters
characteristic The characteristic for which to enable notifications
enable Set to true to enable notifications/indications
Returns
true, if the requested notification status was set successfully
onCharacteristicChanged
就会在本地被调用, 还是符合一般逻辑的,即client告诉server,你如果某个值有变化的话请通知我。
可是如果只是这样世界就完美了,也就不会有那个提问了。调用完这个函数之后,其实gatt server并没有发生什么,这个函数只是在手机本地设置了一下,竟然没有和远端交互。我们可以来看bluedroid中的代码:
/*******************************************************************************
**
** Function BTA_GATTC_RegisterForNotifications
**
** Description This function is called to register for notification of a service.
**
** Parameters client_if - client interface.
** bda - target GATT server.
** p_char_id - pointer to GATT characteristic ID.
**
** Returns OK if registration succeed, otherwise failed.
**
*******************************************************************************/
tBTA_GATT_STATUS BTA_GATTC_RegisterForNotifications (tBTA_GATTC_IF client_if,
BD_ADDR bda,
tBTA_GATTC_CHAR_ID *p_char_id)
{
tBTA_GATTC_RCB *p_clreg;
tBTA_GATT_STATUS status = BTA_GATT_ILLEGAL_PARAMETER;
UINT8 i;
if (!p_char_id)
{
APPL_TRACE_ERROR("deregistration failed, unknow char id");
return status;
}
if ((p_clreg = bta_gattc_cl_get_regcb(client_if)) != NULL)
{
for (i = 0; i < BTA_GATTC_NOTIF_REG_MAX; i ++)
{
if ( p_clreg->notif_reg[i].in_use &&
!memcmp(p_clreg->notif_reg[i].remote_bda, bda, BD_ADDR_LEN) &&
bta_gattc_charid_compare(&p_clreg->notif_reg[i].char_id, p_char_id))
{
APPL_TRACE_WARNING("notification already registered");
status = BTA_GATT_OK;
break;
}
}
if (status != BTA_GATT_OK)
{
for (i = 0; i < BTA_GATTC_NOTIF_REG_MAX; i ++)
{
if (!p_clreg->notif_reg[i].in_use)
{
memset((void *)&p_clreg->notif_reg[i], 0, sizeof(tBTA_GATTC_NOTIF_REG));
p_clreg->notif_reg[i].in_use = TRUE;
memcpy(p_clreg->notif_reg[i].remote_bda, bda, BD_ADDR_LEN);
p_clreg->notif_reg[i].char_id.srvc_id.is_primary = p_char_id->srvc_id.is_primary;
bta_gattc_cpygattid(&p_clreg->notif_reg[i].char_id.srvc_id.id, &p_char_id->srvc_id.id);
bta_gattc_cpygattid(&p_clreg->notif_reg[i].char_id.char_id, &p_char_id->char_id);
status = BTA_GATT_OK;
break;
}
}
if (i == BTA_GATTC_NOTIF_REG_MAX)
{
status = BTA_GATT_NO_RESOURCES;
APPL_TRACE_ERROR("Max Notification Reached, registration failed.");
}
}
}
else
{
APPL_TRACE_ERROR("Client_if: %d Not Registered", client_if);
}
return status;
}
还是要看core spec:
然后再看section3.3.3 写道:
A client may write this configuration descriptor to control the configuration of
this characteristic on the server for the client.
好吧其实一般的思维即是,我调用了前面的接口之后,stack应该办上面设置descriptor的事儿,没有想到完全是两码事……
所以,最终还需要重新写一下这个descriptor,这完全在google的API文档里没有提到嘛,当然在google的例子里面是提到了。可是毕竟会有人没去看这个东西。
对于不熟悉蓝牙的同学来讲是个很大的坑。所以下面这个接口