Device used for testing: Nexus 4, Android 4.3
Connection is working fine but the onCharacteristicChangedMethod of my callback is never called. However I
Well, this API name surely lead some confusions to app developer if he/she was not the Bluetooth background programmer.
From Bluetooth core specification perspective, quote from core spec 4.2 Vol 3, Part G section 3.3.3.3 "Client Characteristic Configuration" :
The characteristic descriptor value is a bit field. When a bit is set, that action shall be enabled, otherwise it will not be used.
and section 4.10
Notifications can be configured using the Client Characteristic Configuration descriptor (See Section 3.3.3.3).
which is clearly states that if client want to receive the notification(or indication,which need response) from server, should write the "Notification" bit to 1("Indication" bit also to 1 otherwise).
However, the name "setCharacteristicNotification" give us a hint is that if we set the parameters of this API as TURE, the client would got notifications; unfortunately this API only set the local bit to allow the notification sent to apps in case of remote notification comes. See code from 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;
}'
so what matters was the descriptor write action.