写特征总是假的
Write characteristic always false
现在我知道这个问题已经被问了大约十亿次了。
我已经阅读了其中的大部分内容(这个网站对我的问题没有太大帮助),我已经阅读了文档,还阅读了示例和教程。
我想做的是:
将 hello world 发送到 BLE 设备(连接到 arduino)
到目前为止我做了什么:
已使用内置设置与设备配对(未编程
我的应用程序中的逻辑)
已使用 GATT 服务器连接到设备。
然而,当我尝试写一个特性时,相应的状态 return 布尔值总是 false。这是最相关的代码:
private void setupServer(BluetoothAdapter bAdapter) {
Log.d(TAG, "Started setting up server");
BluetoothLeAdvertiser bAdvertiser = bAdapter.getBluetoothLeAdvertiser();
if (bAdapter != null) {
bGattServer = bManager.openGattServer(getApplicationContext(), new BluetoothGattServerCallback() {
@Override
public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
super.onConnectionStateChange(device, status, newState);
}
});
//Create a service using a random UUID
//Create characteristics with WRITE property and write a value
BluetoothGattService service = new BluetoothGattService(UUID.randomUUID(), BluetoothGattService.SERVICE_TYPE_PRIMARY);
BluetoothGattCharacteristic bluetoothGattCharacteristic = new BluetoothGattCharacteristic(bUUID, BluetoothGattCharacteristic.PROPERTY_WRITE, BluetoothGattCharacteristic.PERMISSION_WRITE);
Log.d(TAG, "Adding characteristic to service " + service.addCharacteristic(bluetoothGattCharacteristic));
bluetoothGattCharacteristic.setValue("hello");
Log.d(TAG, "Trying to write characteristic..., first value: " + bluetoothGattCharacteristic.getValue()[0]);
if (bGatt != null) {
boolean success = bGatt.writeCharacteristic(bluetoothGattCharacteristic);
if (success) {
Log.d(TAG, "Successfuly wrote characteristic to" + bUUID);
} else {
//THIS ALWAYS EXECUTES??
Log.e(TAG, "Failed to write to characteristic");
}
} else {
Log.e(TAG, "BGATT IS NULL");
}
service.addCharacteristic(bluetoothGattCharacteristic);
bGatt.setCharacteristicNotification(bluetoothGattCharacteristic, true);
bGattServer.addService(service);
}
这些是我的权限:
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-feature android:name="android.hardware.bluetooth_le" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
这是相关代码的其余部分
private boolean scanBluetooth(final BluetoothAdapter bAdapter, final BluetoothDevice[] bDevice) {
final BluetoothLeScanner bScanner = bAdapter.getBluetoothLeScanner();
final boolean[] stopCallback = {false};
Log.d(TAG,"Started scanning");
bScanner.startScan(new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
bDevice[0] = result.getDevice();
if (bDevice[0] == null || stopCallback[0]) {
Toast.makeText(getApplicationContext(), "Didn't find a device", Toast.LENGTH_LONG);
} else {
stopCallback[0] = true;
System.out.println("DEVICE" + bDevice[0]);
bGatt = bDevice[0].connectGatt(getApplicationContext(), true, new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
if(status == BluetoothGatt.GATT_SUCCESS){
Log.d(TAG, "Successful GATT " + newState);
setupServer(bAdapter);
return;
}
if(status == BluetoothGatt.GATT_FAILURE){
Log.e(TAG,"Bigg error boi");
System.exit(1);
}
else{
Log.w(TAG,"Oh no, gatt failed " + status + " retrying");
return;
}
}
@Override
public void onCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {
Log.d(TAG, "Characteristic written" + status);
}
}, BluetoothDevice.TRANSPORT_LE);
Log.d(TAG, "Bgatt value:" + bGatt);
}
}
});
if(bGatt==null){
Log.w(TAG, "BGATT IS NULL WHILE SCANNING");
}
Log.d(TAG, "Finished scanning...");
return true;
}
我使用应用程序 BLEScanner 获得了 bUUID,它显示了一个用于读取和写入的 UUID。我的应用程序的目标是反映该应用程序的功能,但我开始失去理智。我什至不能发送一个简单的 hello world。
Android 工作室输出:
018-12-01 23:58:56.214 25024-25136/com.iopt.davidv7.iopt W/DBG: Oh no, gatt failed 22 retrying
2018-12-01 23:58:56.675 25024-25136/com.iopt.davidv7.iopt D/DBG: Successful GATT 2
2018-12-01 23:58:56.675 25024-25136/com.iopt.davidv7.iopt D/DBG: Started setting up server
2018-12-01 23:58:56.692 25024-25136/com.iopt.davidv7.iopt D/DBG: Adding characteristic to service true
2018-12-01 23:58:56.693 25024-25136/com.iopt.davidv7.iopt D/DBG: Trying to write characteristic..., first value: 104
2018-12-01 23:58:56.693 25024-25136/com.iopt.davidv7.iopt E/DBG: Failed to write to characteristic
客户端是一个简单的 HM-10 蓝牙模块,我想暂时使用 ARDUINO IDE 在串口监视器上镜像我在应用程序中发送的内容。
希望我已经为您提供了所有背景信息,因为我正在失去希望。我没有手动检查权限,因为我已经使用系统对话框设置了它们,但是,只有 "location" 可以启用?这可能是我问题的根源吗?检查蓝牙的 checkSelfPermission,蓝牙管理员 return 是真的,所以我不认为是这样:
if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.BLUETOOTH_ADMIN)
!= PackageManager.PERMISSION_GRANTED) {
Log.e(TAG,"No permission for bluetooth");
// Permission is not granted
}
else{
Log.d(TAG,"Bluetooth permission granted");
}
我的问题似乎是创建新服务,而不是使用发现服务然后解析发现的服务。所以你所做的,算法上是:
1.触发discoverServices(),在回调中又触发onServicesDiscovered()
2. 之后,根据发现的服务创建服务,并根据服务创建特征。因为我现在的硬件只支持一个特性,所以我只能拿出第一个(也是唯一的)服务。
3. 使用 setValue 为服务设置值
4. 为服务添加特征
我不会深入解释我的 readData 代码的作用,但它可能会帮助别人弄清楚如何触发通知并从中读取数据。
private boolean scanBluetooth(final BluetoothAdapter bAdapter, final BluetoothDevice[] bDevice) {
final BluetoothLeScanner bScanner = bAdapter.getBluetoothLeScanner();
final boolean[] stopCallback = {false};
Log.d(TAG,"Started scanning");
bScanner.startScan(new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
bDevice[0] = result.getDevice();
if (bDevice[0] == null || stopCallback[0]) {
Toast.makeText(getApplicationContext(), "Didn't find a device", Toast.LENGTH_LONG);
} else {
stopCallback[0] = true;
System.out.println("DEVICE" + bDevice[0]);
bGatt = bDevice[0].connectGatt(getApplicationContext(), true, new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
if(status == BluetoothGatt.GATT_SUCCESS){
Log.d(TAG, "Successful GATT " + newState);
//Simply triggers a discoverService method, which in return triggers onServiceDiscovered, which writes sample data into the characteristic
setupClient(bAdapter);
return;
}
if(status == BluetoothGatt.GATT_FAILURE){
Log.e(TAG,"Bigg error boi");
System.exit(1);
}
else{
Log.w(TAG,"Oh no, gatt failed " + status + " retrying");
return;
}
}
@Override
//Triggered after we write data in a characteristic
public void onCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {
Log.d(TAG, "Characteristic written" + status);
}
//Triggered when someone(the remote device if everything is set up correctly) changes a characteristic!
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
Log.w(TAG,"Characteristic changed");
try {
Log.d(TAG,"Change characteristic" + new String(characteristic.getValue(),"UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
Log.d(TAG,"Size of discovered" + gatt.getServices().size());
getData(gatt);
writeCharacteristic(gatt);
Log.d(TAG,"Services discovered");
}
}, BluetoothDevice.TRANSPORT_LE);
Log.d(TAG, "Bgatt value:" + bGatt);
}
}
});
if(bGatt==null){
Log.w(TAG, "BGATT IS NULL WHILE SCANNING");
}
Log.d(TAG, "Finished scanning...");
return true;
}
//Doesn't do much, starts discovering services, which triggers onServicesDiscovered
private void setupClient(BluetoothAdapter bAdapter) {
Log.d(TAG, "Started setting up server");
if (bAdapter != null) {
Log.d(TAG, "SERVICE DISCOVERED" + bGatt.discoverServices());
}
}
//Write characteristic into the discovered service
//There is only one characteristic, so we can just take the first index
private void writeCharacteristic(BluetoothGatt gatt){
BluetoothGattService bService = gatt.getService(bUUID);
BluetoothGattCharacteristic bChars = bService.getCharacteristics().get(0);
if(bChars != null){
bChars.setValue("Hello");
bService.addCharacteristic(bChars);
boolean success = gatt.writeCharacteristic(bChars);
if(success){
Log.d(TAG, "Write characteristic successful");
}
else{
Log.e(TAG, "Write characteristic failed");
}
}
else{
Log.e(TAG,"Characteristic not found");
}
}
//Set up notifications for the discovered service!
private void getData(BluetoothGatt gatt){
BluetoothGattService bService = gatt.getService(bUUID);
BluetoothGattCharacteristic bChars = bService.getCharacteristics().get(0);
gatt.setCharacteristicNotification(bChars,true);
}
现在我知道这个问题已经被问了大约十亿次了。
我已经阅读了其中的大部分内容(这个网站对我的问题没有太大帮助),我已经阅读了文档,还阅读了示例和教程。
我想做的是:
将 hello world 发送到 BLE 设备(连接到 arduino)
到目前为止我做了什么:
已使用内置设置与设备配对(未编程 我的应用程序中的逻辑)
已使用 GATT 服务器连接到设备。
然而,当我尝试写一个特性时,相应的状态 return 布尔值总是 false。这是最相关的代码:
private void setupServer(BluetoothAdapter bAdapter) {
Log.d(TAG, "Started setting up server");
BluetoothLeAdvertiser bAdvertiser = bAdapter.getBluetoothLeAdvertiser();
if (bAdapter != null) {
bGattServer = bManager.openGattServer(getApplicationContext(), new BluetoothGattServerCallback() {
@Override
public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
super.onConnectionStateChange(device, status, newState);
}
});
//Create a service using a random UUID
//Create characteristics with WRITE property and write a value
BluetoothGattService service = new BluetoothGattService(UUID.randomUUID(), BluetoothGattService.SERVICE_TYPE_PRIMARY);
BluetoothGattCharacteristic bluetoothGattCharacteristic = new BluetoothGattCharacteristic(bUUID, BluetoothGattCharacteristic.PROPERTY_WRITE, BluetoothGattCharacteristic.PERMISSION_WRITE);
Log.d(TAG, "Adding characteristic to service " + service.addCharacteristic(bluetoothGattCharacteristic));
bluetoothGattCharacteristic.setValue("hello");
Log.d(TAG, "Trying to write characteristic..., first value: " + bluetoothGattCharacteristic.getValue()[0]);
if (bGatt != null) {
boolean success = bGatt.writeCharacteristic(bluetoothGattCharacteristic);
if (success) {
Log.d(TAG, "Successfuly wrote characteristic to" + bUUID);
} else {
//THIS ALWAYS EXECUTES??
Log.e(TAG, "Failed to write to characteristic");
}
} else {
Log.e(TAG, "BGATT IS NULL");
}
service.addCharacteristic(bluetoothGattCharacteristic);
bGatt.setCharacteristicNotification(bluetoothGattCharacteristic, true);
bGattServer.addService(service);
}
这些是我的权限:
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-feature android:name="android.hardware.bluetooth_le" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
这是相关代码的其余部分
private boolean scanBluetooth(final BluetoothAdapter bAdapter, final BluetoothDevice[] bDevice) {
final BluetoothLeScanner bScanner = bAdapter.getBluetoothLeScanner();
final boolean[] stopCallback = {false};
Log.d(TAG,"Started scanning");
bScanner.startScan(new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
bDevice[0] = result.getDevice();
if (bDevice[0] == null || stopCallback[0]) {
Toast.makeText(getApplicationContext(), "Didn't find a device", Toast.LENGTH_LONG);
} else {
stopCallback[0] = true;
System.out.println("DEVICE" + bDevice[0]);
bGatt = bDevice[0].connectGatt(getApplicationContext(), true, new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
if(status == BluetoothGatt.GATT_SUCCESS){
Log.d(TAG, "Successful GATT " + newState);
setupServer(bAdapter);
return;
}
if(status == BluetoothGatt.GATT_FAILURE){
Log.e(TAG,"Bigg error boi");
System.exit(1);
}
else{
Log.w(TAG,"Oh no, gatt failed " + status + " retrying");
return;
}
}
@Override
public void onCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {
Log.d(TAG, "Characteristic written" + status);
}
}, BluetoothDevice.TRANSPORT_LE);
Log.d(TAG, "Bgatt value:" + bGatt);
}
}
});
if(bGatt==null){
Log.w(TAG, "BGATT IS NULL WHILE SCANNING");
}
Log.d(TAG, "Finished scanning...");
return true;
}
我使用应用程序 BLEScanner 获得了 bUUID,它显示了一个用于读取和写入的 UUID。我的应用程序的目标是反映该应用程序的功能,但我开始失去理智。我什至不能发送一个简单的 hello world。
Android 工作室输出:
018-12-01 23:58:56.214 25024-25136/com.iopt.davidv7.iopt W/DBG: Oh no, gatt failed 22 retrying
2018-12-01 23:58:56.675 25024-25136/com.iopt.davidv7.iopt D/DBG: Successful GATT 2
2018-12-01 23:58:56.675 25024-25136/com.iopt.davidv7.iopt D/DBG: Started setting up server
2018-12-01 23:58:56.692 25024-25136/com.iopt.davidv7.iopt D/DBG: Adding characteristic to service true
2018-12-01 23:58:56.693 25024-25136/com.iopt.davidv7.iopt D/DBG: Trying to write characteristic..., first value: 104
2018-12-01 23:58:56.693 25024-25136/com.iopt.davidv7.iopt E/DBG: Failed to write to characteristic
客户端是一个简单的 HM-10 蓝牙模块,我想暂时使用 ARDUINO IDE 在串口监视器上镜像我在应用程序中发送的内容。
希望我已经为您提供了所有背景信息,因为我正在失去希望。我没有手动检查权限,因为我已经使用系统对话框设置了它们,但是,只有 "location" 可以启用?这可能是我问题的根源吗?检查蓝牙的 checkSelfPermission,蓝牙管理员 return 是真的,所以我不认为是这样:
if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.BLUETOOTH_ADMIN)
!= PackageManager.PERMISSION_GRANTED) {
Log.e(TAG,"No permission for bluetooth");
// Permission is not granted
}
else{
Log.d(TAG,"Bluetooth permission granted");
}
我的问题似乎是创建新服务,而不是使用发现服务然后解析发现的服务。所以你所做的,算法上是: 1.触发discoverServices(),在回调中又触发onServicesDiscovered() 2. 之后,根据发现的服务创建服务,并根据服务创建特征。因为我现在的硬件只支持一个特性,所以我只能拿出第一个(也是唯一的)服务。 3. 使用 setValue 为服务设置值 4. 为服务添加特征
我不会深入解释我的 readData 代码的作用,但它可能会帮助别人弄清楚如何触发通知并从中读取数据。
private boolean scanBluetooth(final BluetoothAdapter bAdapter, final BluetoothDevice[] bDevice) {
final BluetoothLeScanner bScanner = bAdapter.getBluetoothLeScanner();
final boolean[] stopCallback = {false};
Log.d(TAG,"Started scanning");
bScanner.startScan(new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
bDevice[0] = result.getDevice();
if (bDevice[0] == null || stopCallback[0]) {
Toast.makeText(getApplicationContext(), "Didn't find a device", Toast.LENGTH_LONG);
} else {
stopCallback[0] = true;
System.out.println("DEVICE" + bDevice[0]);
bGatt = bDevice[0].connectGatt(getApplicationContext(), true, new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
if(status == BluetoothGatt.GATT_SUCCESS){
Log.d(TAG, "Successful GATT " + newState);
//Simply triggers a discoverService method, which in return triggers onServiceDiscovered, which writes sample data into the characteristic
setupClient(bAdapter);
return;
}
if(status == BluetoothGatt.GATT_FAILURE){
Log.e(TAG,"Bigg error boi");
System.exit(1);
}
else{
Log.w(TAG,"Oh no, gatt failed " + status + " retrying");
return;
}
}
@Override
//Triggered after we write data in a characteristic
public void onCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {
Log.d(TAG, "Characteristic written" + status);
}
//Triggered when someone(the remote device if everything is set up correctly) changes a characteristic!
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
Log.w(TAG,"Characteristic changed");
try {
Log.d(TAG,"Change characteristic" + new String(characteristic.getValue(),"UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
Log.d(TAG,"Size of discovered" + gatt.getServices().size());
getData(gatt);
writeCharacteristic(gatt);
Log.d(TAG,"Services discovered");
}
}, BluetoothDevice.TRANSPORT_LE);
Log.d(TAG, "Bgatt value:" + bGatt);
}
}
});
if(bGatt==null){
Log.w(TAG, "BGATT IS NULL WHILE SCANNING");
}
Log.d(TAG, "Finished scanning...");
return true;
}
//Doesn't do much, starts discovering services, which triggers onServicesDiscovered
private void setupClient(BluetoothAdapter bAdapter) {
Log.d(TAG, "Started setting up server");
if (bAdapter != null) {
Log.d(TAG, "SERVICE DISCOVERED" + bGatt.discoverServices());
}
}
//Write characteristic into the discovered service
//There is only one characteristic, so we can just take the first index
private void writeCharacteristic(BluetoothGatt gatt){
BluetoothGattService bService = gatt.getService(bUUID);
BluetoothGattCharacteristic bChars = bService.getCharacteristics().get(0);
if(bChars != null){
bChars.setValue("Hello");
bService.addCharacteristic(bChars);
boolean success = gatt.writeCharacteristic(bChars);
if(success){
Log.d(TAG, "Write characteristic successful");
}
else{
Log.e(TAG, "Write characteristic failed");
}
}
else{
Log.e(TAG,"Characteristic not found");
}
}
//Set up notifications for the discovered service!
private void getData(BluetoothGatt gatt){
BluetoothGattService bService = gatt.getService(bUUID);
BluetoothGattCharacteristic bChars = bService.getCharacteristics().get(0);
gatt.setCharacteristicNotification(bChars,true);
}