我无法弄清楚当特征值改变时如何触发通知。 onCharacteristicChanged的方法永远不会被调用,但我知道这个值每2秒就会改变一次。我通过在发现服务时调用readCharacteristic然后反复调用此事实来解决这个问题。我不相信这是正确的方式,而我只应该在onCharacteristicChanged方法发送广播时阅读。是否有可能通知工作或这是最好的方法?
设备控制器:
public class WarningActivity extends AppCompatActivity {
private static final String TAG = "WarningActivity Class";
private BluetoothLeService mBluetoothLeService;
public static WarningActivity wInstance;
private boolean mConnected = false;
private String mDeviceAddress;
private boolean quitService;
private TextView connectStatus;
private Button connectButton;
private Button cameraButton;
private BluetoothManager mBluetoothManager;
private Vibrator vib;
private Uri notification;
private Ringtone ring;
private final ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder service) {
mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
if (!mBluetoothLeService.initialize()) {
Log.e(TAG, "Unable to initialize Bluetooth");
finish();
}
mBluetoothLeService.connect(mDeviceAddress);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
mBluetoothLeService = null;
}
};
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
mConnected = true;
} else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
mConnected = false;
} else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
Log.i("Data: ", mBluetoothLeService.getSupportedGattService().toString());
BluetoothGattService mService = mBluetoothLeService.getSupportedGattService();
BluetoothGattCharacteristic characteristic = mService.getCharacteristic(mBluetoothLeService.ALERT_UUID);
mBluetoothLeService.setCharacteristicNotification(characteristic, true);
mBluetoothLeService.readCharacteristic(characteristic);
} else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
BluetoothGattService mService = mBluetoothLeService.getSupportedGattService();
BluetoothGattCharacteristic characteristic = mService.getCharacteristic(mBluetoothLeService.ALERT_UUID);
byte[] temp = intent.getByteArrayExtra(BluetoothLeService.EXTRA_DATA);
String tempString = Arrays.toString(temp);
Log.i("Data: ", Arrays.toString(temp));
mBluetoothLeService.readCharacteristic(characteristic);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ColorDrawable colorDrawable = new ColorDrawable(Color.parseColor("#268011"));
getSupportActionBar().setBackgroundDrawable(colorDrawable);
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
connectButton = (Button) findViewById(R.id.connectButton);
connectButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.connected_logo, 0, 0);
connectButton.setClickable(false);
Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
Intent intent = getIntent();
mDeviceAddress = intent.getStringExtra("EXTRA_DEVICE_ADDRESS");
mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
vib = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
ring = RingtoneManager.getRingtone(getApplicationContext(), notification);
wInstance = this;
quitService = false;
connectStatus = (TextView) findViewById(R.id.connectMessage);
connectStatus.setText("Connected to: \n " + mDeviceAddress);
}
@Override
protected void onResume() {
super.onResume();
registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
if (mBluetoothLeService != null) {
final boolean result = mBluetoothLeService.connect(mDeviceAddress);
Log.d(TAG, "Connect request result=" + result);
}
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(mGattUpdateReceiver);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(mServiceConnection);
mBluetoothLeService = null;
}
private static IntentFilter makeGattUpdateIntentFilter() {
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
return intentFilter;
}
}
BluetoothLeService
public class BluetoothLeService extends Service {
private final static String TAG = BluetoothLeService.class.getSimpleName();
private BluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothAdapter;
private String mBluetoothDeviceAddress;
private BluetoothGatt mBluetoothGatt;
private int mConnectionState = STATE_DISCONNECTED;
private static final int STATE_DISCONNECTED = 0;
private static final int STATE_CONNECTING = 1;
private static final int STATE_CONNECTED = 2;
public final static String ACTION_GATT_CONNECTED = "ACTION_GATT_CONNECTED";
public final static String ACTION_GATT_DISCONNECTED = "ACTION_GATT_DISCONNECTED";
public final static String ACTION_GATT_SERVICES_DISCOVERED = "ACTION_GATT_SERVICES_DISCOVERED";
public final static String ACTION_DATA_AVAILABLE = "ACTION_DATA_AVAILABLE";
public final static String EXTRA_DATA = "EXTRA_DATA";
public final static UUID SERVICE_UUID = UUID.fromString(GattAttributes.BLE_SERVICE);
public final static UUID ALERT_UUID = UUID.fromString(GattAttributes.BLE_ALERT_CHARACTERISTIC);
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
String intentAction;
if (newState == BluetoothProfile.STATE_CONNECTED) {
intentAction = ACTION_GATT_CONNECTED;
mConnectionState = STATE_CONNECTED;
broadcastUpdate(intentAction);
Log.i(TAG, "Connected to GATT server.");
Log.i(TAG, "Attempting to start service discovery:" + mBluetoothGatt.discoverServices());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
intentAction = ACTION_GATT_DISCONNECTED;
mConnectionState = STATE_DISCONNECTED;
Log.i(TAG, "Disconnected from GATT server.");
broadcastUpdate(intentAction);
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
Log.i("BlueToothService: ", "onCharacteristicRead " + characteristic.toString());
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
Log.i("BlueToothService: ", "onCharacteristicChanged " + characteristic.toString());
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
};
private void broadcastUpdate(final String action) {
final Intent intent = new Intent(action);
Log.i("BlueToothService: ", "BroadcastUpdate ActionOnly: " + action);
sendBroadcast(intent);
}
private void broadcastUpdate(final String action, final BluetoothGattCharacteristic characteristic) {
final Intent intent = new Intent(action);
Log.i("BlueToothService: ", "BroadcastUpdateLong " + characteristic.toString() + " Action:" + action);
intent.putExtra(EXTRA_DATA, characteristic.getValue());
sendBroadcast(intent);
}
public class LocalBinder extends Binder {
BluetoothLeService getService() {
return BluetoothLeService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
close();
return super.onUnbind(intent);
}
private final IBinder mBinder = new LocalBinder();
public boolean initialize() {
// For API level 18 and above, get a reference to BluetoothAdapter through
if (mBluetoothManager == null) {
mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
if (mBluetoothManager == null) {
Log.e(TAG, "Unable to initialize BluetoothManager.");
return false;
}
}
mBluetoothAdapter = mBluetoothManager.getAdapter();
if (mBluetoothAdapter == null) {
Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
return false;
}
return true;
}
public boolean connect(final String address) {
if (mBluetoothAdapter == null || address == null) {
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
return false;
}
if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress) && mBluetoothGatt != null) {
Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
if (mBluetoothGatt.connect()) {
mConnectionState = STATE_CONNECTING;
return true;
} else {
return false;
}
}
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
if (device == null) {
Log.w(TAG, "Device not found. Unable to connect.");
return false;
}
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
Log.d(TAG, "Trying to create a new connection.");
mBluetoothDeviceAddress = address;
mConnectionState = STATE_CONNECTING;
return true;
}
public void disconnect() {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.disconnect();
}
public void close() {
if (mBluetoothGatt == null) {
return;
}
mBluetoothGatt.close();
mBluetoothGatt = null;
}
public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.readCharacteristic(characteristic);
}
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
if (SERVICE_UUID.equals(characteristic.getUuid())) {
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(ALERT_UUID);
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
}
}
public BluetoothGattService getSupportedGattService() {
if (mBluetoothGatt == null) return null;
return mBluetoothGatt.getService(SERVICE_UUID);
}
}
答案 0 :(得分:2)
找到解决方案:错误的经典案例和错误的描述符UUID。在哪里我找到了答案BLE GATT onCharacteristicChanged not called after subscribing to notification。错误类型在setCharacteristicNotification方法中。更改为ALERT_UUID以及我假设正确的描述符UUID的文章
Uri