gpt4 book ai didi

android - Rxandroid ble 重连处理指南

转载 作者:行者123 更新时间:2023-11-29 23:41:54 31 4
gpt4 key购买 nike

[更新]

断开连接后我可以重新连接到 ble 设备,但似乎无法读取或写入任何特征。 Logcat 在重新连接后吐出这个,这是我的应用程序做错了什么还是因为 ble 设备?

08-09 15:05:45.109 9601-10364/com.project.app D/BluetoothGatt: setCharacteristicNotification() - uuid: cb67d1e1-cfb5-45f5-9123-3f07d9189f1b enable: false
08-09 15:05:45.111 9601-10352/com.project.app D/RxBle#ConnectionOperationQueue: STARTED DescriptorWriteOperation(54881118)
08-09 15:05:45.114 9601-10364/com.project.app D/RxBle#ConnectionOperationQueue: QUEUED DescriptorWriteOperation(191754430)
08-09 15:05:45.116 9601-9601/com.project.app D/BtleConnManager: RETRY 2/-1 :::: com.polidea.rxandroidble.exceptions.BleCannotSetCharacteristicNotificationException
08-09 15:06:15.117 9601-10352/com.project.app D/RxBle#ConnectionOperationQueue: FINISHED DescriptorWriteOperation(54881118)
08-09 15:06:15.118 9601-10365/com.project.app D/BluetoothGatt: setCharacteristicNotification() - uuid: cb67d0e1-cfb5-45f5-9123-3f07d9189f1b enable: false
08-09 15:06:15.120 9601-10352/com.project.app D/RxBle#ConnectionOperationQueue: STARTED DescriptorWriteOperation(88995281)
08-09 15:06:15.124 9601-10365/com.project.app D/RxBle#ConnectionOperationQueue: QUEUED DescriptorWriteOperation(108601267)
08-09 15:06:15.124 9601-10366/com.project.app D/BluetoothGatt: setCharacteristicNotification() - uuid: cb67d1e1-cfb5-45f5-9123-3f07d9189f1b enable: true
08-09 15:06:15.126 9601-9601/com.project.app D/BtleConnManager: RETRY 2/-1 :::: com.polidea.rxandroidble.exceptions.BleCannotSetCharacteristicNotificationException
08-09 15:06:15.131 9601-10366/com.project.app D/RxBle#ConnectionOperationQueue: QUEUED DescriptorWriteOperation(98838561)
08-09 15:06:45.126 9601-10352/com.project.app D/RxBle#ConnectionOperationQueue: FINISHED DescriptorWriteOperation(88995281)

[更新]

使用 rxandroidble1 和 rxjava1

您好,我是 rxjava 和 ble 连接概念的新手,但我已经投入到一个文档很少的现有项目中,并且在连接丢失后处理重新连接时遇到问题。

我已经检查了 rxandroidble 的示例应用程序,但它只处理连接,如果它失去连接则不会重新连接。或者图书馆应该自己处理它还是我遗漏了什么。

一般问题可以这样描述:

  1. 我将电话应用程序连接到我的蓝牙设备。一切都按预期工作,当我的 ble 设备上的温度发生变化时,我会从我的订阅中收到通知。

  2. 我通过关闭设备上的 ble 芯片或关闭手机上的蓝牙或走出有效范围而断开连接。

  3. 我再次打开手机或蓝牙设备上的蓝牙。

  4. 我设法重新连接,但我的订阅没有重新订阅,所以当温度或其他值发生变化时,我的手机没有收到任何通知。

根据我的雇主的说法,这段代码在过去应该可以正常工作,但在它断开连接后我似乎无法让它工作。那么你们中的任何人都可以看到代码逻辑中的任何错误吗?或者 ble 设备可能有问题?或者这是 RxBleConnectionSharingAdapter 的常见错误或问题还是什么?我已经尝试了一切,但似乎没有任何效果。

还是我在 onUnsibcribeMethod 之类的地方遗漏了什么?

我想建立连接方法是代码中最相关的部分。在通过测试方法重新连接后,我尝试重新订阅一个特性,但应用程序随后崩溃了。

这是我的连接管理器类:

private static final String TAG = "HELLOP";
private static RxBleClient rxBleClient;
private RxBleConnection rxBleConnection;

private static final int MAX_RETRIES = 10;
private static final int SHORT_RETRY_DELAY_MS = 1000;
private static final int LONG_RETRY_DELAY_MS = 30000;

private final Context mContext;
private final String mMacAddress;
private final String gatewayName;
private final RxBleDevice mBleDevice;
private PublishSubject<Void> mDisconnectTriggerSubject = PublishSubject.create();
private Observable<RxBleConnection> mConnectionObservable;
private final ProjectDeviceManager mProjectDeviceManager;
private BehaviorSubject<Boolean> connectionStatusSubject = BehaviorSubject.create();
private boolean isAutoSignIn = false;
private BondStateReceiver bondStateReceiver;
private boolean isBonded = false;


//gets the client
public static RxBleClient getRxBleClient(Context context) {
if (rxBleClient == null) {
// rxBleClient = /*MockedClient.getClient();*/RxBleClient.create(this);
// RxBleClient.setLogLevel(RxBleLog.DEBUG);
// super.onCreate();
rxBleClient = RxBleClient.create(context);
RxBleClient.setLogLevel(RxBleLog.DEBUG);
}
return rxBleClient;
}

public BtleConnectionManager(final Context context, final String macAddress, String name) {
mContext = context;
mMacAddress = macAddress;
gatewayName = name;
mBleDevice = getRxBleClient(context).getBleDevice(macAddress);
mProjectDeviceManager = new ProjectDeviceManager(this);
}

@Override
public final Context getContext() {
return mContext;
}

@Override
public final ProjectDeviceManager getProjectDeviceManager() {
return mProjectDeviceManager;
}

@Override
public final boolean isConnected() {
return mBleDevice.getConnectionState() == RxBleConnection.RxBleConnectionState.CONNECTED;
}

@Override
public String getConnectionName() {
if (gatewayName != null && !gatewayName.isEmpty()) {
return gatewayName;
} else {
return mMacAddress;
}
}

final RxBleDevice getBleDevice() {
return mBleDevice;
}

public final synchronized Observable<RxBleConnection> getConnection() {
if (mConnectionObservable == null || mBleDevice.getConnectionState() == RxBleConnection.RxBleConnectionState.DISCONNECTED
|| mBleDevice.getConnectionState() == RxBleConnection.RxBleConnectionState.DISCONNECTING) {
establishConnection();
}
return mConnectionObservable;
}

public void goBack() {
Intent intent = null;
try {
intent = new Intent(mContext,
Class.forName("com.Project.dcpapp.BluetoothActivity"));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
((Activity) mContext).startActivity(intent);
((Activity) mContext).finish();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}

public void setAutoSignIn(boolean value) {
this.isAutoSignIn = value;
}

public boolean getAutoSignIn() {
return this.isAutoSignIn;
}

@Override
public void pause() {
}

@Override
public void resume() {
}

@Override
public Observable<Boolean> observeConnectionStatus() {
return connectionStatusSubject;
}

@Override
public Calendar getLastConnectionTime() {
return mProjectDeviceManager.getLastUpdateTime();
}

public void disconnect() {
BluetoothDevice bluetoothDevice = getBleDevice().getBluetoothDevice();
Log.d("BtleConnManager", " disconnect " + bluetoothDevice.getBondState());
Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
@Override
public void run() {
mDisconnectTriggerSubject.onNext(null);
mConnectionObservable = null;
}
}, 700);

}

public void removeBond() {
Method m = null;
BluetoothDevice bluetoothDevice = getBleDevice().getBluetoothDevice();
Log.d("BtleConnManager", " removeBond " + bluetoothDevice.getBondState());
if (bluetoothDevice.getBondState() == BluetoothDevice.BOND_BONDED) {
try {
m = bluetoothDevice.getClass().getMethod("removeBond", (Class[]) null);
m.invoke(bluetoothDevice, (Object[]) null);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}

public void bond() {
BluetoothDevice bluetoothDevice = getBleDevice().getBluetoothDevice();
Log.d("BtleConnManager ", "bond state " + bluetoothDevice.getBondState());
if (bluetoothDevice.getBondState() == BluetoothDevice.BOND_NONE
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
bondStateReceiver = new BondStateReceiver();
final IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
getContext().registerReceiver(bondStateReceiver, filter);
bluetoothDevice.createBond();
}
}

public void setBonded(boolean value) {
this.isBonded = value;
}

public boolean isBonded() {
return this.isBonded;
}

private class BondStateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) {
final int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR);
switch (state) {
case BluetoothDevice.BOND_BONDED:
setBonded(true);
Log.d("BtleConManager", "Bonded ");
break;
case BluetoothDevice.BOND_BONDING:
Log.d("BtleConManager", "Bonding ");
break;
case BluetoothDevice.BOND_NONE:
Log.d("BtleConManager", "unbonded ");
setBonded(false);
final int prevState = intent.getIntExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, BluetoothDevice.ERROR);
if (prevState == BluetoothDevice.BOND_BONDING) {
Toast.makeText(getContext(), R.string.error_bluetooth_bonding_failed, Toast.LENGTH_LONG).show();
}
break;
}
}
}
}

private void establishConnection() {
Log.d("BtleConnManager", " establishConnection");
mConnectionObservable = mBleDevice
.establishConnection(false)
.observeOn(AndroidSchedulers.mainThread())
.doOnNext(rxBleConnection -> {
// Save connection to use if retry is done when already connected
this.rxBleConnection = rxBleConnection;
// Notify observers that connection is established
connectionStatusSubject.onNext(true);

})

.onErrorResumeNext(error -> {
// Return the saved connection if already connected
if (error instanceof BleAlreadyConnectedException && rxBleConnection != null) {
return Observable.just(rxBleConnection);

} else {
return Observable.error(error);
}
})
//.retryWhen(getRetryRule()) Do not retry connect here - retry when using getConnection instead (otherwise a double retry connection will be done)
.takeUntil(mDisconnectTriggerSubject)
.doOnError(throwable -> {

this.rxBleConnection = null;
if (!isConnected()) {
// Notify observers that connection has failed
connectionStatusSubject.onNext(false);
}
}).doOnUnsubscribe(() -> {
Log.d("BtleConnManager", "establishConnection Unsubscribe ");
connectionStatusSubject.onNext(false);

}).doOnCompleted(() -> Log.d("BtleConnManager", "establishConnection completed"))
.doOnSubscribe(() -> {

})
//.subscribeOn(AndroidSchedulers.mainThread())
//.compose(bindUntilEvent(PAUSE))
.compose(new ConnectionSharingAdapter());


}


public void test(){
mConnectionObservable
.flatMap(rxBleConnection -> rxBleConnection.setupNotification(UUID.fromString("cb67d1c1-cfb5-45f5-9123-3f07d9189f1b")))
.flatMap(notificationObservable -> notificationObservable)
.observeOn(AndroidSchedulers.mainThread())
.retryWhen(errors -> errors.flatMap(error -> {
if (error instanceof BleDisconnectedException) {
Log.d("Retry", "Retrying");
return Observable.just(null);
}
return Observable.error(error);
}))
.doOnError(throwable -> {

Log.d(TAG, "establishConnection: " + throwable.getMessage());

})
.subscribe(bytes -> {
Log.d(TAG, "establishConnection: characteristics changed" + new String(bytes));
// React on characteristic changes
});
}


public RetryWithDelay getRetryRule() {
return new RetryWithDelay(MAX_RETRIES, SHORT_RETRY_DELAY_MS);
}

public RetryWithDelay getInfiniteRetryRule() {
return new RetryWithDelay(RetryWithDelay.NO_MAX, LONG_RETRY_DELAY_MS);
}

public class RetryWithDelay implements
Func1<Observable<? extends Throwable>, Observable<?>> {

public static final int NO_MAX = -1;

private final int maxRetries;
private final int retryDelayMs;
private int retryCount;

public RetryWithDelay(final int maxRetries, final int retryDelayMs) {
this.maxRetries = maxRetries;
this.retryDelayMs = retryDelayMs;
this.retryCount = 0;
}

@Override
public Observable<?> call(Observable<? extends Throwable> attempts) {
return attempts
.flatMap(new Func1<Throwable, Observable<?>>() {
@Override
public Observable<?> call(Throwable throwable) {
++retryCount;
if (mConnectionObservable == null) {
// If manually disconnected return empty observable
return Observable.empty();
} else if (throwable instanceof BleAlreadyConnectedException) {
return Observable.error(throwable);
} else if (retryCount < maxRetries || maxRetries == NO_MAX) {
Log.d("BtleConnManager", " RETRY " + retryCount + "/" + maxRetries + " :::: " + throwable.getClass().getName());
// When this Observable calls onNext, the original
// Observable will be retried (i.e. re-subscribed).
return Observable.timer(retryDelayMs, TimeUnit.MILLISECONDS);
} else {
//Last try
Log.d("BtleConnManager", " LAST RETRY " + retryCount + "/" + maxRetries + " :::: " + throwable.getClass().getName());
return Observable.error(throwable);
}
}
});
}
}

最佳答案

在 establishConnection 中,您将 autoConnect 参数设置为 false,这将阻止自动重新连接。如果您将其设置为 true,它应该会自动重新连接。参见 https://stackoverflow.com/a/40187086/556495http://polidea.github.io/RxAndroidBle/在自动连接下。

请注意,如果在手机/平板电脑上关闭/重新启动蓝牙,这将不起作用。因此,您可能还需要一个蓝牙状态更改广播监听器,以便在发生这种情况时重新启动一切。

关于android - Rxandroid ble 重连处理指南,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51765386/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com