void notifyValueChanged(@NonNull final BluetoothDevice device, @Nullable final byte[] value) {
		// Keep a reference to the value callback, as it may change during execution
		final DataReceivedCallback valueCallback = this.valueCallback;

		// With no value callback there is no need for any merging
		if (valueCallback == null) {
			return;
		}

		if (dataMerger == null && (packetFilter == null || packetFilter.filter(value))) {
			final Data data = new Data(value);
			handler.post(() -> {
				try {
					valueCallback.onDataReceived(device, data);
				} catch (final Throwable t) {
					Log.e(TAG, "Exception in Value callback", t);
				}
			});
		} else {
			final int currentCount = count;
			handler.post(() -> {
				if (progressCallback != null) {
					try {
						progressCallback.onPacketReceived(device, value, currentCount);
					} catch (final Throwable t) {
						Log.e(TAG, "Exception in Progress callback", t);
					}
				}
			});
			if (buffer == null)
				buffer = new DataStream();
			if (dataMerger.merge(buffer, value, count++)) {
				final byte[] merged = buffer.toByteArray();
				if (packetFilter == null || packetFilter.filter(merged)) {
					final Data data = new Data(merged);
					handler.post(() -> {
						try {
							valueCallback.onDataReceived(device, data);
						} catch (final Throwable t) {
							Log.e(TAG, "Exception in Value callback", t);
						}
					});
				}
				buffer = null;
				count = 0;
			} // else
			// wait for more packets to be merged
		}
	}
Sets a callback that will be executed when the device services were invalidated (i.e. on
disconnection) or the callback has been unregistered and it can release resources.

@param callback the callback.
@return The request.
ble/src/main/java/no/nordicsemi/android/ble/ValueChangedCallback.java