【发布时间】:2018-03-24 23:38:55
【问题描述】:
我正在开发一个 Android 应用程序,它每天必须连接 +/- 120 台 BLE GATT 服务器,这些服务器中至少有 3 台同时具有完全相同的服务和特性的服务器。尽管遵循所有标准和默认模式,但我一直在使用 Android BLE 遇到各种问题。
每天都会发生这种情况,我必须至少一次将平板电脑重置为默认设置,因为“蓝牙已停止工作”,我无法找到导致此问题的原因。 这非常令人沮丧,我无法忍受每天进行这种类型的维护(硬重置)。
起初,我尝试了适用于 Android SDK 18 的 BLE,它的行为非常奇怪,仅使用一天就显示出糟糕的结果。 所以我开始使用 Lollipop 版本的操纵 Android BLE,它显示了一些改进。
我已经遇到这些问题好几天了,都是因为我得到了意想不到的结果,例如 onCharacteristicRead 返回但数据为空。 或者例如,我在使用 STATE_CONNECTED 的 onConnectionStateChanged 之后调用 discoverServices(),所以在一段时间后调用 onServicesDiscovered() 但 getServices() 返回 null。 所有这些问题仅在与第一台服务器断开连接后才会发生。它连接的第一台服务器正确读取和写入所有内容,但随后我断开连接()和 onConnectionStateChanged(),然后我关闭()。然后我连接到下一个服务器,我开始遇到这些问题(所有 GATT 操作都在主线程上,所有连接都正确建立并正确处理),所以我必须断开连接并连接以便可以应用程序读取 GATT属性正确。
我有 3 个要阅读的特征,读完第 3 个后,我开始写 3 个特征。
我浏览了蓝牙日志,可以看到发生了意想不到的事情。此日志是应用正确读取所有内容的时间(它始终是应用连接到的第一台 GATT 服务器):
10-11 09:08:05.350 15989-15989/efp.android.sample D/BluetoothAdapter: STATE_ON
10-11 09:08:05.350 15989-15989/efp.android.sample D/BluetoothAdapter: STATE_ON
10-11 09:08:05.350 15989-15989/efp.android.sample D/BluetoothLeScanner: Start Scan
10-11 09:08:05.351 15989-15989/efp.android.sample D/BluetoothAdapter: STATE_ON
10-11 09:08:05.352 15989-15989/efp.android.sample D/BluetoothAdapter: STATE_ON
10-11 09:08:05.353 15989-15989/efp.android.sample D/BluetoothAdapter: STATE_ON
10-11 09:08:05.354 15989-15989/efp.android.sample D/BluetoothAdapter: STATE_ON
10-11 09:08:05.362 15989-15994/efp.android.sample I/art: Do partial code cache collection, code=48KB, data=60KB
10-11 09:08:05.362 15989-15994/efp.android.sample I/art: After code cache collection, code=48KB, data=60KB
10-11 09:08:05.362 15989-15994/efp.android.sample I/art: Increasing code cache capacity to 256KB
10-11 09:08:05.457 15989-16002/efp.android.sample D/BluetoothLeScanner: onClientRegistered() - status=0 clientIf=5 mClientIf=0
10-11 09:08:05.513 15989-15989/efp.android.sample W/IInputConnectionWrapper: getCursorCapsMode on inactive InputConnection
10-11 09:08:05.681 15989-16023/efp.android.sample D/ScanRecord: parseFromBytes
10-11 09:08:05.681 15989-15989/efp.android.sample D/LAURASTAR_BLE: onScanResult
10-11 09:08:05.682 15989-15989/efp.android.sample D/BluetoothAdapter: STATE_ON
10-11 09:08:05.683 15989-15989/efp.android.sample D/BluetoothAdapter: STATE_ON
10-11 09:08:05.684 15989-15989/efp.android.sample D/BluetoothAdapter: STATE_ON
10-11 09:08:05.685 15989-15989/efp.android.sample D/BluetoothAdapter: STATE_ON
10-11 09:08:05.685 15989-15989/efp.android.sample D/BluetoothLeScanner: Stop Scan
10-11 09:08:05.692 15989-15989/efp.android.sample D/BluetoothGatt: connect() - device: F5:8E:C1:91:DC:CC, auto: false
10-11 09:08:05.692 15989-15989/efp.android.sample D/BluetoothAdapter: isSecureModeEnabled
10-11 09:08:05.699 15989-15989/efp.android.sample D/BluetoothGatt: registerApp()
10-11 09:08:05.699 15989-15989/efp.android.sample D/BluetoothGatt: registerApp() - UUID=ebf41986-8aad-4796-a537-7319c00f0f46
10-11 09:08:05.802 15989-16002/efp.android.sample D/BluetoothGatt: onClientRegistered() - status=0 clientIf=5
10-11 09:08:06.332 15989-16001/efp.android.sample D/LAURASTAR_BLE: onConnectionStateChange:
10-11 09:08:06.332 15989-16001/efp.android.sample D/BluetoothGatt: discoverServices() - device: F5:8E:C1:91:DC:CC
10-11 09:08:06.343 15989-16002/efp.android.sample D/BluetoothGatt: onSearchComplete() = Device=F5:8E:C1:91:DC:CC Status=0
10-11 09:08:06.343 15989-16002/efp.android.sample D/LAURASTAR_BLE: onServicesDiscovered:
10-11 09:08:07.143 15989-16002/efp.android.sample W/BluetoothGatt: onCharacteristicRead() - Device=F5:8E:C1:91:DC:CC handle=51 Status=0
10-11 09:08:07.233 15989-16002/efp.android.sample W/BluetoothGatt: onCharacteristicRead() - Device=F5:8E:C1:91:DC:CC handle=14 Status=0
10-11 09:08:07.324 15989-16023/efp.android.sample W/BluetoothGatt: onCharacteristicRead() - Device=F5:8E:C1:91:DC:CC handle=23 Status=0
10-11 09:08:08.136 15989-16023/efp.android.sample D/BluetoothGatt: cancelOpen() - device: F5:8E:C1:91:DC:CC
10-11 09:08:08.146 15989-16001/efp.android.sample D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=5 device=F5:8E:C1:91:DC:CC
10-11 09:08:08.151 15989-16001/efp.android.sample D/LAURASTAR_BLE: onConnectionStateChange:
10-11 09:08:08.265 15989-15989/efp.android.sample D/BluetoothGatt: close()
10-11 09:08:08.266 15989-15989/efp.android.sample D/BluetoothGatt: unregisterApp() - mClientIf=5
从第一个 GATT 服务器断开连接以连接到第二个 GATT 服务器后,我必须不断断开并重新连接才能读取特征,尽管它总是正确读取第一个特征。
这是读取出现问题时的日志...因此,如果读取出现错误,我需要断开连接并重新连接(即使重新连接后读取出现错误,它也会关闭、扫描并重试)。
10-12 08:03:48.133 30409-30409/efp.android.sample D/BluetoothAdapter: STATE_ON
10-12 08:03:48.133 30409-30409/efp.android.sample D/BluetoothAdapter: STATE_ON
10-12 08:03:48.134 30409-30409/efp.android.sample D/BluetoothLeScanner: Start Scan
10-12 08:03:48.134 30409-30409/efp.android.sample D/BluetoothAdapter: STATE_ON
10-12 08:03:48.137 30409-30409/efp.android.sample D/BluetoothAdapter: STATE_ON
10-12 08:03:48.260 30409-31121/efp.android.sample D/BluetoothLeScanner: onClientRegistered() - status=0 clientIf=6 mClientIf=0
10-12 08:03:48.391 30409-30422/efp.android.sample D/ScanRecord: parseFromBytes
10-12 08:03:48.395 30409-30409/efp.android.sample D/LAURASTAR_BLE: onScanResult
10-12 08:03:48.397 30409-30409/efp.android.sample D/BluetoothAdapter: STATE_ON
10-12 08:03:48.397 30409-30409/efp.android.sample D/BluetoothAdapter: STATE_ON
10-12 08:03:48.398 30409-30409/efp.android.sample D/BluetoothAdapter: STATE_ON
10-12 08:03:48.399 30409-30409/efp.android.sample D/BluetoothAdapter: STATE_ON
10-12 08:03:48.399 30409-30409/efp.android.sample D/BluetoothLeScanner: Stop Scan
10-12 08:03:48.410 30409-30409/efp.android.sample D/BluetoothGatt: connect() - device: F5:8E:C1:91:DC:CC, auto: false
10-12 08:03:48.410 30409-30409/efp.android.sample D/BluetoothAdapter: isSecureModeEnabled
10-12 08:03:48.411 30409-30409/efp.android.sample D/BluetoothGatt: registerApp()
10-12 08:03:48.411 30409-30409/efp.android.sample D/BluetoothGatt: registerApp() - UUID=ce6919e5-e4f7-4180-a313-557e168a7c5a
10-12 08:03:48.514 30409-30422/efp.android.sample D/BluetoothGatt: onClientRegistered() - status=0 clientIf=6
10-12 08:03:48.745 30409-31121/efp.android.sample D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=6 device=F5:8E:C1:91:DC:CC
10-12 08:03:48.755 30409-31121/efp.android.sample D/BluetoothGatt: discoverServices() - device: F5:8E:C1:91:DC:CC
10-12 08:03:48.915 30409-30414/efp.android.sample I/art: Do partial code cache collection, code=19KB, data=28KB
10-12 08:03:48.916 30409-30414/efp.android.sample I/art: After code cache collection, code=19KB, data=28KB
10-12 08:03:48.916 30409-30414/efp.android.sample I/art: Increasing code cache capacity to 128KB
10-12 08:03:48.982 30409-30422/efp.android.sample D/BluetoothGatt: onClientConnParamsChanged() - Device=F5:8E:C1:91:DC:CC interval=6 status=0 (I DONT THINK THIS SHOULD HAPPEN)
10-12 08:03:49.688 30409-30421/efp.android.sample D/BluetoothGatt: onSearchComplete() = Device=F5:8E:C1:91:DC:CC Status=0
10-12 08:03:49.689 30409-30421/efp.android.sample D/LAURASTAR_BLE: onServicesDiscovered:
10-12 08:03:49.711 30409-30422/efp.android.sample D/BluetoothGatt: onClientConnParamsChanged() - Device=F5:8E:C1:91:DC:CC interval=36 status=0
10-12 08:03:50.467 30409-31121/efp.android.sample W/BluetoothGatt: onCharacteristicRead() - Device=F5:8E:C1:91:DC:CC handle=51 Status=0
10-12 08:03:50.557 30409-30422/efp.android.sample W/BluetoothGatt: onCharacteristicRead() - Device=F5:8E:C1:91:DC:CC handle=14 Status=5 (status NOT SUCCESS ...)
10-12 08:03:50.830 30409-30422/efp.android.sample D/BluetoothGatt: onClientConnParamsChanged() - Device=F5:8E:C1:91:DC:CC interval=6 status=0
10-12 08:03:51.533 30409-31121/efp.android.sample W/BluetoothGatt: onCharacteristicRead() - Device=F5:8E:C1:91:DC:CC handle=14 Status=137 (status NOT SUCCESS ...)
10-12 08:03:51.533 30409-31121/efp.android.sample D/LAURASTAR_BLE: Data is empty. (null)
10-12 08:03:51.533 30409-31121/efp.android.sample D/BluetoothGatt: cancelOpen() - device: F5:8E:C1:91:DC:CC
10-12 08:03:51.561 30409-30422/efp.android.sample D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=6 device=F5:8E:C1:91:DC:CC
10-12 08:03:51.565 30409-30422/efp.android.sample D/LAURASTAR_BLE: onConnectionStateChange:
10-12 08:03:51.565 30409-30422/efp.android.sample D/BluetoothAdapter: isSecureModeEnabled
10-12 08:03:51.609 30409-31121/efp.android.sample D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=6 device=F5:8E:C1:91:DC:CC
10-12 08:03:51.610 30409-31121/efp.android.sample D/LAURASTAR_BLE: onConnectionStateChange:
10-12 08:03:51.610 30409-31121/efp.android.sample D/BluetoothGatt: discoverServices() - device: F5:8E:C1:91:DC:CC
10-12 08:04:01.091 30409-31121/efp.android.sample D/BluetoothGatt: onSearchComplete() = Device=F5:8E:C1:91:DC:CC Status=0
10-12 08:04:01.091 30409-31121/efp.android.sample D/LAURASTAR_BLE: onServicesDiscovered:
10-12 08:04:02.048 30409-31121/efp.android.sample W/BluetoothGatt: onCharacteristicRead() - Device=F5:8E:C1:91:DC:CC handle=51 Status=0
10-12 08:04:02.438 30409-30421/efp.android.sample W/BluetoothGatt: onCharacteristicRead() - Device=F5:8E:C1:91:DC:CC handle=14 Status=0
10-12 08:04:02.829 30409-30421/efp.android.sample W/BluetoothGatt: onCharacteristicRead() - Device=F5:8E:C1:91:DC:CC handle=23 Status=0
10-12 08:04:02.898 30409-30414/efp.android.sample I/art: Do partial code cache collection, code=48KB, data=61KB
10-12 08:04:02.899 30409-30414/efp.android.sample I/art: After code cache collection, code=48KB, data=61KB
10-12 08:04:02.899 30409-30414/efp.android.sample I/art: Increasing code cache capacity to 256KB
10-12 08:04:04.389 30409-30422/efp.android.sample D/BluetoothGatt: cancelOpen() - device: F5:8E:C1:91:DC:CC
10-12 08:04:04.402 30409-30421/efp.android.sample D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=6 device=F5:8E:C1:91:DC:CC
10-12 08:04:04.406 30409-30421/efp.android.sample D/LAURASTAR_BLE: onConnectionStateChange:
10-12 08:04:04.502 30409-30409/efp.android.sample V/InputMethodManager: Starting input: tba=android.view.inputmethod.EditorInfo@d981ae5 nm : efp.android.sample ic=com.android.internal.widget.EditableInputConnection@41369ba
10-12 08:04:04.502 30409-30409/efp.android.sample I/InputMethodManager: [IMM] startInputInner - mService.startInputOrWindowGainedFocus
10-12 08:04:04.503 30409-30409/efp.android.sample D/InputTransport: Input channel constructed: fd=70
10-12 08:04:04.503 30409-30409/efp.android.sample D/InputTransport: Input channel destroyed: fd=73
10-12 08:04:04.519 30409-30409/efp.android.sample D/BluetoothGatt: close()
10-12 08:04:04.520 30409-30409/efp.android.sample D/BluetoothGatt: unregisterApp() - mClientIf=6
在这个日志中,这是可见的,在成功读取第一个特征后:
W/BluetoothGatt: onCharacteristicRead() - Device=F5:8E:C1:91:DC:CC handle=14 Status=5
然后 onClientConnParamsChanged 在调用 discoverServices() 之后调用,在调用 onServicesDiscovered() 之前调用。
我所有的代码似乎都是正确的...... 所以逻辑如下:
首先接收用户想要的服务器mac地址,以便应用扫描并找到它。
我在 EditText 中实现了 TextWatcher,因此当用户插入 mac 地址时,应用程序会查找插入地址的 BLE 设备。
String macToFind = "";
private class ScanIronFieldsTextWatcher implements TextWatcher {
View view;
public ScanIronFieldsTextWatcher(View view) { this.view = view; }
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
public void afterTextChanged(Editable editable) {
switch (view.getId()) {
case R.id.txt_mac_address: {
String originalText = txtMacAddress.getText().toString().toUpperCase();
String macToFind = Tools.getValidMacAddress(originalText);
if(mConnectedGatt != null && mConnectedGatt.getDevice().getAddress().equals(macToFind)) {
mConnectedGatt.connect();
}
else {
if(mConnectedGatt != null) {
mConnectedGatt.close();
mConnectedGatt = null;
}
//Search mac address
writeToActivityLog("Looking for " + macToFind +"...", LogAdapter.MESSAGE_TYPE_NORMAL);
hideKeyboard();
startScan();
}
}
}
}
}
用户插入mac地址后,启动startScan()。
startScan()
private void startScan() {
if (!mBluetoothAdapter.isEnabled()) {
writeToActivityLog("Bluetooth is off!", LogAdapter.MESSAGE_TYPE_ERROR);
return;
}
try {
ScanFilter scanFilter = new ScanFilter.Builder().setDeviceAddress(macToFind).build();
ArrayList<ScanFilter> filters = new ArrayList<ScanFilter>();
filters.add(scanFilter);
ScanSettings settings = new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_BALANCED).build();
mBluetoothAdapter.getBluetoothLeScanner().startScan(filters, settings, mScanCallback);
retryingHandler = new Handler();
retryingHandler.postDelayed(new Runnable() {
@Override
public void run() {
showProgress(false);
stopScan();
if (mDevices.size() == 0) {
writeToActivityLog("Server not found.", LogAdapter.MESSAGE_TYPE_ERROR);
} else {
mDevices.clear();
}
}
}, SCAN_TIME);
} catch (IllegalArgumentException e) {
writeToActivityLog("Invalid Address!", LogAdapter.MESSAGE_TYPE_ERROR);
}
}
mScanCallback:
private ScanCallback mScanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
Log.d(TAG, "onScanResult");
processResult(result);
}
@Override
public void onBatchScanResults(List<ScanResult> results) {
Log.d(TAG, "onBatchScanResults: "+results.size()+" results");
for (ScanResult result : results) {
processResult(result);
}
}
@Override
public void onScanFailed(int errorCode) { Log.w(TAG, "LE Scan Failed: "+errorCode); }
private void processResult(final ScanResult result) {
runOnUiThread(new Runnable() {
@Override
public void run() {
if(mConnectedGatt == null) {
stopScan();
final BluetoothDevice device = result.getDevice();
mDevices.put(device.hashCode(), device);
writeToActivityLog("Server found!", LogAdapter.MESSAGE_TYPE_NORMAL);
writeToActivityLog("Connecting to " + macToFind + "...", LogAdapter.MESSAGE_TYPE_NORMAL);
mConnectedGatt = device.connectGatt(NewDeviceControlActivity.this, false, mGattCallback);
retryingHandler.removeCallbacksAndMessages(null);
}
}
});
}
};
mGattCallback
private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
if (newState == BluetoothProfile.STATE_CONNECTED) {
writeToActivityLog("Connected.", LogAdapter.MESSAGE_TYPE_SUCCESS);
mConnected = true;
if(!gatt.discoverServices()) {
writeToActivityLog("Impossible discoverServices().", LogAdapter.MESSAGE_TYPE_ERROR);
if(!retrying)
retrying = true;
mConnectedGatt.disconnect();
}
}
else if(newState == BluetoothProfile.STATE_DISCONNECTED) {
writeToActivityLog("Disconnected.", LogAdapter.MESSAGE_TYPE_NORMAL);
if(!currentIron.hasCompletedSetup()) {
showProgress(true);
if(retrying) {
writeToActivityLog("Trying again...", LogAdapter.MESSAGE_TYPE_NORMAL);
if(mConnectedGatt != null)
mConnectedGatt.connect();
}
else {
writeToActivityLog("Trying again but also scanning again... (r)", LogAdapter.MESSAGE_TYPE_NORMAL);
retrying = false;
if(mConnectedGatt != null)
mConnectedGatt.close();
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
startScan();
}
}, 2000);
}
}
}
}
@Override
public void onServicesDiscovered(final BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
Log.d(TAG, "onServicesDiscovered:");
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
startObtainingIronData(gatt);
}
}, 700);
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic, final int status) {
super.onCharacteristicRead(gatt, characteristic, status);
byte[] data = characteristic.getValue();
if(status != BluetoothGatt.GATT_SUCCESS) {
runOnUiThread(new Runnable() { @Override public void run() {Toast.makeText(NewDeviceControlActivity.this, ("BluetoothGatt: Response != GATT_SUCCESS ("+status+")."), Toast.LENGTH_SHORT).show();}});
}
if (characteristic.getUuid().toString().contains(Iron.IRON_CODES[4])) {
//First characteristic read succesfully
final String version = new String(data);
runOnUiThread(new Runnable() { @Override public void run() {Toast.makeText(NewDeviceControlActivity.this, ("Version "+version), Toast.LENGTH_SHORT).show();}});
//Request to read second characteristic
BluetoothGattCharacteristic characteristic2 = getCharacteristic(gatt, Iron.IRON_CODES[0]);
gatt.readCharacteristic(characteristic2);
}
else if (characteristic.getUuid().toString().contains(Iron.IRON_CODES[0])) {
//Read second characteristic
if(data == null || data.length == 0) { //returns with status=137
Log.d(TAG, "Data is empty " + (data == null ? "(null)" : data));//This ALWAYS happens except the first server the app connects too
writeToActivityLog("Data is empty. "+ (data == null ? "(null)" : data), LogAdapter.MESSAGE_TYPE_ERROR);
if(!retrying)
retrying = true;
mConnectedGatt.disconnect();
return;
}
else {
if (data[2] == 4) {
//Request to read third characteristic
BluetoothGattCharacteristic characteristic2 = getCharacteristic(gatt, Iron.IRON_CODES[1]);
if(characteristic2 != null)
gatt.readCharacteristic(characteristic2);
else {
writeToActivityLog("Impossible readCharacteristic Machine Type" , LogAdapter.MESSAGE_TYPE_ERROR);
if(!retrying)
retrying = true;
mConnectedGatt.disconnect();
}
}
}
}
else if (characteristic.getUuid().toString().contains(Iron.IRON_CODES[1])) {
//Read third characteristic
if(data[0] == 0) {
BluetoothGattCharacteristic characteristic2 = getCharacteristic(gatt, Iron.IRON_CODES[2]);
long now = System.currentTimeMillis();
byte[] nowBytes = new byte[]{(byte) ((int) (now & 255L)), (byte) ((int) (now >> 8)), (byte) ((int) (now >> 16)), (byte) ((int) (now >> 24))};
characteristic2.setValue(nowBytes);
writeToActivityLog("Read all information succesfully.", LogAdapter.MESSAGE_TYPE_NORMAL);
//Request to write first characteristic
if (!gatt.writeCharacteristic(characteristic2)){
writeToActivityLog("Impossible to write timestamp.", LogAdapter.MESSAGE_TYPE_ERROR);
if(!retrying)
retrying = true;
mConnectedGatt.disconnect();
}
}
}
}
@Override
public void onCharacteristicWrite(final BluetoothGatt gatt, BluetoothGattCharacteristic characteristic2, int status) {
super.onCharacteristicWrite(gatt, characteristic2, status);
if(status == BluetoothGatt.GATT_SUCCESS) {
showProgress(false);
if(characteristic2.getUuid().toString().contains(Iron.IRON_CODES[2])) {
//Wrote first characteristic
String intToWrite = "0x01";
BluetoothGattCharacteristic characteristic = getCharacteristic(gatt, Iron.IRON_CODES[1]);
characteristic.setValue(Integer.decode(intToWrite), BluetoothGattCharacteristic.FORMAT_UINT8, 0);
//Request to write second characteristic
if (!gatt.writeCharacteristic(characteristic)) {
writeToActivityLog("Impossible to write first characteristic!.", LogAdapter.MESSAGE_TYPE_ERROR);
if(!retrying)
retrying = true;
mConnectedGatt.disconnect();
}
}
else if(characteristic2.getUuid().toString().contains(Iron.IRON_CODES[1])) {
//Wrote second characteristic
service.sendData(), new Callback<String>() {
@Override
public void onResponse(Call<String> call, Response<String> response) {
//Write third characteristic
BluetoothGattCharacteristic characteristic = getCharacteristic(gatt, Iron.IRON_CODES[3]);
characteristic.setValue(0x40, android.bluetooth.BluetoothGattCharacteristic.FORMAT_UINT8, 0);
gatt.writeCharacteristic(characteristic);
}
@Override
public void onFailure(Call<String> call, Throwable t) {
if(mConnectedGatt != null)
mConnectedGatt.disconnect();
}
});
}
}
else if(characteristic2.getUuid().toString().contains(Iron.IRON_CODES[3])) {
//Wrote third characteristic
writeToActivityLog("Data written successfully.", LogAdapter.MESSAGE_TYPE_SUCCESS);
if(mConnectedGatt != null)
mConnectedGatt.disconnect();
}
}
}
};
我尝试在 runOnUIThread 中运行所有 mConnectedGatt 操作,但结果相同。所有 UUID 的特征都是正确的,并且正在写入的特征AREN'T与正在读取的相同。
我没有 GATT 服务器“离开”应用程序的问题,也没有太远。 我在三个三星 Galaxy Tab A 10.1 2016 上运行该软件,其中 都返回相同的结果。
所以我的结果基本上是这些:
预期(仅在应用连接到的第一台服务器上发生):
- 正在寻找MAC
- 找到服务器!
- 连接到 MAC
- 已连接。
- (读取第一个特征)版本:
- (读取第二个特征)
- (读取第三个特征)
- (写第一个特征)
- (写第二个特征)
- (写第三个特征)
- 已断开连接。
会发生什么(尝试连接到另一台服务器):
- 正在寻找MAC
- 找到服务器!
- 连接到 MAC
- 已连接。
- (读取第一个特征)版本:
- 数据为空! (空)
- 已断开连接。
- 再试一次...
- 已连接。
- (读取第一个特征)版本:
- (读取第二个特征)
- (读取第三个特征)
- (写第一个特征)
- (写第二个特征)
- (写第三个特征)
- 已断开连接。
我猜很多重新连接是导致“蓝牙已停止工作”的原因。 我不知道为什么会这样!
请,如果有人可以花一些时间帮助我弄清楚发生了什么,我将不胜感激...... 谢谢
【问题讨论】:
-
您是否在项目中添加了一些新的 ble 服务?如果可能,您可以尝试清除蓝牙缓存。转到设置-> 应用程序单击右上角的更多图标。点击系统应用。从列表中选择蓝牙。清除存储。 (有时候第一次不清除缓存,点两下这个按钮)希望能解决问题
-
@hasbi 新的 ble 服务是什么意思?
-
我的意思是添加新特性
-
值得一提的是,在你提供的sn-p中,没有处理GATT操作失败
(status != BluetoothGatt.GATT_SUCCESS)。这意味着可能会调用onConnectionStateChange来通知连接,而在先前连接时,可能会调用onServicesDiscovered,但gatt 客户端与先前的客户端对象相关。最后,onClientConnectionState与问题无关,它只是告知客户端/服务器已经交换了一些协议细节,例如使用的通道、优先级等。
标签: java android bluetooth bluetooth-lowenergy