我正在尝试通过使用 Android Studio 和 Java 构建应用程序来管理 BLE 设备。我在处理 BLE 设备中识别的特征的属性时遇到困难。
这是我的活动代码,用于读取与特征相关的属性。
Properties.java:
public class Properties extends AppCompatActivity {
private static final String TAG = "Properties";
private BluetoothGattCharacteristic characteristic;
private BluetoothGatt gatt;
private Button btnRead, btnWrite, btnNotify;
private boolean isNotifying = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_properties);
btnRead = findViewById(R.id.btnRead);
btnWrite = findViewById(R.id.btnWrite);
btnNotify = findViewById(R.id.btnNotify);
// Retrieve the characteristic UUID from the Intent
String characteristicUUID = getIntent().getStringExtra("characteristicUUID");
// Retrieve the BluetoothGatt and find the characteristic by UUID
gatt = GattManager.getGatt();
if (gatt == null) {
Log.e(TAG, "No Gatt instance received from MainActivity to Properties");
} else {
Log.d(TAG, "Gatt instance received from MainActivity to Properties");
}
characteristic = findCharacteristicByUUID(characteristicUUID);
if (characteristic == null) {
Log.e(TAG, "No BluetoothGattCharacteristic received from intent to Properties");
} else {
Log.d(TAG, "BluetoothGattCharacteristic received from intent to Properties");
}
// check and enable available properties
if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_READ) != 0) {
btnRead.setVisibility(View.VISIBLE);
btnRead.setOnClickListener(view -> readCharacteristic());
}
if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE) != 0) {
btnWrite.setVisibility(View.VISIBLE);
btnWrite.setOnClickListener(view -> writeCharacteristic());
}
if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_NOTIFY) != 0) {
btnNotify.setVisibility(View.VISIBLE);
btnNotify.setOnClickListener(view -> toggleNotify());
}
}
private BluetoothGattCharacteristic findCharacteristicByUUID(String uuid) {
if (gatt != null) {
for (BluetoothGattService service : gatt.getServices()) {
for (BluetoothGattCharacteristic characteristic : service.getCharacteristics()) {
if (characteristic.getUuid().toString().equals(uuid)) {
return characteristic;
}
}
}
}
return null;
}
private void readCharacteristic() {
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
return;
}
gatt.readCharacteristic(characteristic);
onCharacteristicRead(characteristic);
}
private void writeCharacteristic() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Write Value");
final EditText input = new EditText(this);
builder.setView(input);
builder.setPositiveButton("OK", (dialog, which) -> {
String value = input.getText().toString();
characteristic.setValue(value.getBytes());
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
return;
}
boolean success = gatt.writeCharacteristic(characteristic);
if (success) {
Toast.makeText(this, "Write successful", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "Write failed", Toast.LENGTH_SHORT).show();
}
});
builder.setNegativeButton("Cancel", (dialog, which) -> dialog.cancel());
builder.show();
}
private void toggleNotify() {
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
if (!isNotifying) {
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
return;
}
gatt.setCharacteristicNotification(characteristic, true);
if (descriptor != null) {
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
gatt.writeDescriptor(descriptor);
}
btnNotify.setText("Stop Notify");
Toast.makeText(this, "Notifications enabled", Toast.LENGTH_SHORT).show();
} else {
gatt.setCharacteristicNotification(characteristic, false);
if (descriptor != null) {
descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
gatt.writeDescriptor(descriptor);
}
btnNotify.setText("Start Notify");
Toast.makeText(this, "Notifications disabled", Toast.LENGTH_SHORT).show();
}
isNotifying = !isNotifying;
}
public void onCharacteristicRead(BluetoothGattCharacteristic characteristic) {
// Display characteristic value in a dialog
String value = new String(characteristic.getValue());
new AlertDialog.Builder(this)
.setTitle("Characteristic Value")
.setMessage("Value: " + value)
.setPositiveButton("OK", null)
.show();
}
}
我从
BluetoothGattCallBack
调用MainActivity.java
,并将Gatt
保存在GattManager.java
中。
GattManager.java:
public class GattManager {
private static BluetoothGatt gatt;
public static BluetoothGatt getGatt() {
return gatt;
}
public static void setGatt(BluetoothGatt gattInstance) {
gatt = gattInstance;
}
}
请帮助我解决错误并管理具有特征的读取、写入和通知属性。
我已经根据给出的代码进行了尝试,但是我在管理读写属性方面遇到了问题。
虽然我看不到你的所有代码,但我认为你在读取特性方面遇到的麻烦是因为你试图以同步操作的方式读取,而从 BLE 读取是异步的。
你正在这样做:
gatt.readCharacteristic(characteristic);
...
String value = new String(characteristic.getValue());
这不起作用,因为您尝试读取的值还不存在。调用BluetoothGatt.readCharacteristic(characteristic)后,结果将通过BluetoothGattCallback.onCharacteristicRead(gatt,characteristic,status)到达。当您调用BluetoothDevice.connectGatt()时,您提供一个BluetoothGattCallback。您需要重写 onCharacteristicRead() 以在值到达时对其进行处理。该值也可能无法读取,在这种情况下,您可以检查该方法的状态参数。
我假设你在 MainActivity 的某个地方调用 connectGatt() ?根据您当前的设置,从 Properties 调用 BluetoothGatt.readCharacteristic(characteristic) 并在 MainActivity 中进行回调将会很困难。您可能想让 GattManager 做更多的事情,例如管理回调或存储特征值。因此,当回调在 onCharacteristicRead() 中接收到值时,它会将值保存在 GattManager 中,然后 Properties 可以读取它。您甚至可以向 GattManager 添加一个侦听器机制,其中 Properties 可以注册以在特征值到达时接收事件。或者使用 LiveData。有很多方法可以让它发挥作用!