Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/187.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 扫描自动停止:BluetoothAdapter:stopLeScan()_Android_Rxandroidble - Fatal编程技术网

Android 扫描自动停止:BluetoothAdapter:stopLeScan()

Android 扫描自动停止:BluetoothAdapter:stopLeScan(),android,rxandroidble,Android,Rxandroidble,BluetoothManager是一个负责与可扩展设备交互的类。 它作为带有RxBleClient的Singleton注入,并开始扫描片段/服务的start方法。 有时扫描会自动停止,有时几秒钟后,我找不到原因 问题是,设备仍在广播其包,但我的应用程序无法接收,因为BluetoothAdapter已经停止了扫描 以下是服务中扫描的日志: 03-09 11:17:58.526 10196-10196/com.turboegg.storm D/BluetoothManager  ***   212:

BluetoothManager是一个负责与可扩展设备交互的类。
它作为带有RxBleClient的Singleton注入,并开始扫描片段/服务的start方法。 有时扫描会自动停止,有时几秒钟后,我找不到原因

问题是,设备仍在广播其包,但我的应用程序无法接收,因为BluetoothAdapter已经停止了扫描

以下是服务中扫描的日志:

03-09 11:17:58.526 10196-10196/com.turboegg.storm D/BluetoothManager  ***   212: Clear scan
03-09 11:17:58.527 10196-10196/com.turboegg.storm D/BluetoothManager  ***   72: Start scanning
03-09 11:17:58.579 10196-10196/com.turboegg.storm I/AppCompatViewInflater: app:theme is now deprecated. Please move to using android:theme instead.
03-09 11:17:58.589 10196-10196/com.turboegg.storm I/AppCompatViewInflater: app:theme is now deprecated. Please move to using android:theme instead.
03-09 11:17:58.602 10196-10196/com.turboegg.storm I/AppCompatViewInflater: app:theme is now deprecated. Please move to using android:theme instead.
03-09 11:17:58.604 10196-10196/com.turboegg.storm I/AppCompatViewInflater: app:theme is now deprecated. Please move to using android:theme instead.
03-09 11:18:01.592 10196-10196/com.turboegg.storm D/BluetoothAdapter: startLeScan(): null
03-09 11:18:01.596 10196-10196/com.turboegg.storm D/BluetoothAdapter: STATE_ON
03-09 11:18:01.600 10196-10207/com.turboegg.storm D/BluetoothLeScanner: onClientRegistered() - status=0 clientIf=8
03-09 11:18:01.656 10196-10196/com.turboegg.storm D/BluetoothManager  ***   79: Device C6:86:B6:35:FF:00
03-09 11:18:01.784 10196-10196/com.turboegg.storm D/BluetoothManager  ***   79: Device EE:AC:C7:32:9A:F6
03-09 11:18:02.643 10196-10196/com.turboegg.storm D/BluetoothManager  ***   79: Device C6:86:B6:35:FF:00
03-09 11:18:02.835 10196-10196/com.turboegg.storm D/BluetoothManager  ***   79: Device EE:AC:C7:32:9A:F6
03-09 11:18:03.659 10196-10196/com.turboegg.storm D/BluetoothManager  ***   79: Device C6:86:B6:35:FF:00
03-09 11:18:03.796 10196-10196/com.turboegg.storm D/BluetoothManager  ***   79: Device EE:AC:C7:32:9A:F6
03-09 11:18:04.663 10196-10196/com.turboegg.storm D/BluetoothManager  ***   79: Device C6:86:B6:35:FF:00
03-09 11:18:04.785 10196-10196/com.turboegg.storm D/BluetoothManager  ***   79: Device EE:AC:C7:32:9A:F6
03-09 11:18:05.648 10196-10196/com.turboegg.storm D/BluetoothManager  ***   79: Device C6:86:B6:35:FF:00
03-09 11:18:05.809 10196-10196/com.turboegg.storm D/BluetoothManager  ***   79: Device EE:AC:C7:32:9A:F6
03-09 11:18:06.817 10196-10196/com.turboegg.storm D/BluetoothManager  ***   79: Device EE:AC:C7:32:9A:F6
03-09 11:18:07.672 10196-10196/com.turboegg.storm D/BluetoothManager  ***   79: Device C6:86:B6:35:FF:00
03-09 11:18:07.827 10196-10196/com.turboegg.storm D/BluetoothManager  ***   79: Device EE:AC:C7:32:9A:F6
03-09 11:18:08.682 10196-10196/com.turboegg.storm D/BluetoothManager  ***   79: Device C6:86:B6:35:FF:00
03-09 11:18:08.826 10196-10196/com.turboegg.storm D/BluetoothManager  ***   79: Device EE:AC:C7:32:9A:F6
03-09 11:18:09.009 10196-10196/com.turboegg.storm D/BluetoothAdapter: stopLeScan()
03-09 11:18:09.011 10196-10196/com.turboegg.storm D/BluetoothAdapter: STATE_ON
这是BluetoohManager:

public class BluetoothManager {

    private Context context;
    private RxBleClient rxBleClient;
    private StorageManager storageManager;
    private Subscription scanSubscription, connectionSubscription, notificationSubscription, writeSubscription, keepAwakenSubscription;
    private RxBleDevice connectedDevice;
    private RxBleConnection activeConnection;

    public BluetoothManager(Context context, RxBleClient rxBleClient, StorageManager storageManager) {
        this.context = context;
        this.rxBleClient = rxBleClient;
        this.storageManager = storageManager;
    }

    public void onDestroy() {
        stop();
        storageManager.setAllSensorsDisconnectible();
        storageManager.clearResources();
    }

    public void stop() {
        clearScan();
        disconnect();
    }

    public void stopScan() {
        clearScan();
    }

    public void disconnect() {
        clearConnection();
        clearNotification();
        clearWrite();
        clearKeepAwaken();
    }

    public void startScan() {
        clearScan();
        Timber.d("Start scanning");
        scanSubscription = Observable.timer(3, TimeUnit.SECONDS)
                .flatMap(ignored -> rxBleClient.scanBleDevices())
                .filter(rxBleScanResult -> CommonUtils.isStormSensor(rxBleScanResult.getBleDevice()))
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(rxBleScanResult -> {
                    RxBleDevice device = rxBleScanResult.getBleDevice();
                    Timber.d("Device %s", device.getMacAddress());
                    if (device.getMacAddress() != null && !storageManager.containsDiscoveredDevice(device.getMacAddress())) {
                        Timber.d("Found device, %s %s", device.getName(), device.getMacAddress());
                        storageManager.addDiscoveredSensor(device.getMacAddress(), device.getName());
                        EventBus.getDefault().post(new DeviceDiscovered(device.getMacAddress(), device.getName()));
                    }
                    storageManager.setSensorConnectible(device.getMacAddress(), Calendar.getInstance().getTime());
                }, this::onBleFailure);
    }

    public void connectDevice(String macAddress, String outInDoor) {
        disconnect();
        connectedDevice = rxBleClient.getBleDevice(macAddress);
        if (connectedDevice != null) {
            Timber.d("Start connecting to %s", macAddress);
            connectionSubscription = connectedDevice.establishConnection(context, false)
                    .subscribe(connection -> {
                        // Need to delay write operations due to sensor processor limitations
                        writeCharacteristic(connection, CommonUtils.getBleTime())
                                .delay(AppConstants.BLUETOOTH_WRITE_DELAY_MILIS, TimeUnit.MILLISECONDS);
                        writeCharacteristic(connection, AppConstants.BLUETOOTH_SET_BUZZER_OFF)
                                .delay(AppConstants.BLUETOOTH_WRITE_DELAY_MILIS, TimeUnit.MILLISECONDS);
                        writeCharacteristic(connection, AppConstants.BLUETOOTH_SET_MASK)
                                .delay(AppConstants.BLUETOOTH_WRITE_DELAY_MILIS, TimeUnit.MILLISECONDS);
                        writeCharacteristic(connection, AppConstants.BLUETOOTH_CLEAR_STATS)
                                .delay(AppConstants.BLUETOOTH_WRITE_DELAY_MILIS, TimeUnit.MILLISECONDS);
                        writeCharacteristic(connection, AppConstants.BLUETOOTH_CLEAR_MEM)
                                .delay(AppConstants.BLUETOOTH_WRITE_DELAY_MILIS, TimeUnit.MILLISECONDS);
                        writeCharacteristic(connection, outInDoor)
                                .delay(AppConstants.BLUETOOTH_WRITE_DELAY_MILIS, TimeUnit.MILLISECONDS);
                        writeCharacteristic(connection, AppConstants.BLUETOOTH_CLEAR_MASK)
                                .delay(AppConstants.BLUETOOTH_WRITE_DELAY_MILIS, TimeUnit.MILLISECONDS);
                        writeCharacteristic(connection, AppConstants.BLUETOOTH_SET_MASK)
                                .delay(AppConstants.BLUETOOTH_WRITE_DELAY_MILIS, TimeUnit.MILLISECONDS);
                        activeConnection = connection;
                        getBasicParams(connection, macAddress);
                        subscribeForNotifications(connection, macAddress);
                    }, throwable -> {
                        Timber.e("Error while connecting " + throwable.toString());
                        handleConnectionError(macAddress);
                        disconnect();
                    });
        }
    }

    public void writeOutInDoor(String outInDoor) {
        clearWrite();
        writeSubscription = Observable.combineLatest(
                writeCharacteristic(activeConnection, AppConstants.BLUETOOTH_CLEAR_STATS)
                        .delay(AppConstants.BLUETOOTH_WRITE_DELAY_MILIS, TimeUnit.MILLISECONDS),
                writeCharacteristic(activeConnection, AppConstants.BLUETOOTH_CLEAR_MEM)
                        .delay(AppConstants.BLUETOOTH_WRITE_DELAY_MILIS, TimeUnit.MILLISECONDS),
                writeCharacteristic(activeConnection, outInDoor)
                        .delay(AppConstants.BLUETOOTH_WRITE_DELAY_MILIS, TimeUnit.MILLISECONDS),
                writeCharacteristic(activeConnection, AppConstants.BLUETOOTH_CLEAR_MASK)
                        .delay(AppConstants.BLUETOOTH_WRITE_DELAY_MILIS, TimeUnit.MILLISECONDS),
                writeCharacteristic(activeConnection, AppConstants.BLUETOOTH_SET_MASK)
                        .delay(AppConstants.BLUETOOTH_WRITE_DELAY_MILIS, TimeUnit.MILLISECONDS),
                (bytes, bytes2, value, bytes4, bytes5) -> value)
                .subscribe(value -> Timber.d("Written value %s", new String(value)),
                        throwable -> Timber.e("Error writing outInDoor: %s", throwable.toString())
                );
    }

    public void handleDeviceStatus(boolean checked) {
        if (checked) {
            keepDeviceAwaken();
        } else {
            clearKeepAwaken();
        }
    }

    public void handleDeviceDisconnection(String macAddress) {
        if (connectedDevice != null && connectedDevice.getMacAddress().equals(macAddress)) {
            disconnect();
        }
    }

    /**
     * Private methods
     */

    private void getBasicParams(RxBleConnection connection, String macAddress) {
        Observable.combineLatest(
                connection.readCharacteristic(AppConstants.BLUETOOTH_UUID_BATTERY),
                connection.readCharacteristic(AppConstants.BLUETOOTH_UUID_FIRMWARE),
                (bytes, bytes2) -> new DeviceConnected(bytes, bytes2, macAddress))
                .take(1)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(deviceConnected -> {
                    Timber.d("Bat %s", deviceConnected.getBattery());
                    Timber.d("Fmw %s", deviceConnected.getFirmware());
                    storageManager.updateSensorInfo(macAddress, deviceConnected.getBattery(), deviceConnected.getFirmware());
                    storageManager.setSensorConnected(macAddress);
                    handleDeviceStatus(storageManager.getStormSensor(macAddress).isStatusChecked());
                    EventBus.getDefault().post(deviceConnected);
                }, throwable -> Timber.e("Sensor basic info error %s", throwable.getMessage()));

    }

    private void subscribeForNotifications(RxBleConnection connection, String macAddress) {
        notificationSubscription = Observable.combineLatest(
                connection.setupNotification(AppConstants.BLUETOOTH_UUID_EVENT)
                        .<byte[]>flatMap(observable -> observable),
                connection.setupNotification(AppConstants.BLUETOOTH_UUID_DISTANCE)
                        .<byte[]>flatMap(observable -> observable),
                NotificationStormEvent::new)
                .filter(CommonUtils::isStormEvent)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(notificationStormEvent -> {
                    Timber.d("New storm, event: %s, distance %s km", notificationStormEvent.getEvent(), notificationStormEvent.getDistance());
                    storageManager.addStormEvent(Calendar.getInstance().getTime(), notificationStormEvent.getDistance());
                    EventBus.getDefault().post(notificationStormEvent);
                }, throwable -> Timber.e("Notification error %s", throwable.toString()));
    }

    private void keepDeviceAwaken() {
        clearKeepAwaken();
        keepAwakenSubscription = Observable.interval(
                AppConstants.BLUETOOTH_KEEP_AWAKE_MINS, AppConstants.BLUETOOTH_KEEP_AWAKE_MINS, TimeUnit.MINUTES)
                .flatMap(aLong -> writeCharacteristic(activeConnection, CommonUtils.getBleTime()))
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(bytes -> Timber.d("Written value %s to keep device awaken", new String(bytes)),
                        throwable -> Timber.e("Error keeping awake %s", throwable.toString()));
    }

    private void onBleFailure(Throwable throwable) {
        if (throwable instanceof BleScanException) {
            handleBleScanException((BleScanException) throwable);
        }
    }

    private void clearScan() {
        Timber.d("Clear scan");
        if (scanSubscription != null) {
            scanSubscription.unsubscribe();
            Timber.d("Clear unsubscribed");
        }
        scanSubscription = null;
    }

    private void clearConnection() {
        if (connectionSubscription != null) connectionSubscription.unsubscribe();
        connectionSubscription = null;
        connectedDevice = null;
        activeConnection = null;
    }

    private void clearNotification() {
        if (notificationSubscription != null) notificationSubscription.unsubscribe();
        notificationSubscription = null;
    }

    private void clearWrite() {
        if (writeSubscription != null) writeSubscription.unsubscribe();
        writeSubscription = null;
    }

    private void clearKeepAwaken() {
        if (keepAwakenSubscription != null) keepAwakenSubscription.unsubscribe();
        keepAwakenSubscription = null;
    }

    private Observable<byte[]> writeCharacteristic(RxBleConnection connection, String value) {
        byte[] bytesToWrite = value.getBytes(StandardCharsets.UTF_8);
        return connection.writeCharacteristic(AppConstants.BLUETOOTH_UUID_UART_WRITE, bytesToWrite);
    }

    private void handleBleScanException(BleScanException bleScanException) {
        switch (bleScanException.getReason()) {
            case BleScanException.BLUETOOTH_NOT_AVAILABLE:
                Timber.e("Bluetooth is not available");
                break;
            case BleScanException.BLUETOOTH_DISABLED:
                Timber.e("Enable bluetooth and try again");
                break;
            case BleScanException.LOCATION_PERMISSION_MISSING:
                Timber.e("On Android 6.0 location permission is required. Implement Runtime Permissions ");
                break;
            case BleScanException.LOCATION_SERVICES_DISABLED:
                Timber.e("Location services needs to be enabled on Android 6.0");
                break;
            case BleScanException.BLUETOOTH_CANNOT_START:
            default:
                Timber.e("Unable to onStart scanning");
                break;
        }
    }

    private void handleConnectionError(String macAddress) {
        // This is the case where e.g. connection was lost or the device was turned off
        // Need to call for realm to modify the sensor object in different thread
        Realm realm = Realm.getDefaultInstance();
        realm.executeTransaction(realm1 -> {
            StormSensor sensor = realm1.where(StormSensor.class).equalTo(AppConstants.STORM_SENSOR_MAC_ADDRESS, macAddress).findFirst();
            sensor.setConnected(false);
        });
        realm.close();
    }
}
公共类BluetoothManager{
私人语境;
私人RxBleClient RxBleClient;
私人存储管理器;
私人订阅扫描订阅、连接订阅、通知订阅、写订阅、保留订阅;
专用RxBleDevice连接设备;
专用RxBleConnection活动连接;
公共BluetoothManager(上下文上下文、RxBleClient RxBleClient、StorageManager StorageManager){
this.context=上下文;
this.rxBleClient=rxBleClient;
this.storageManager=storageManager;
}
公共空间{
停止();
storageManager.setAllSensorsDisconnectable();
storageManager.clearResources();
}
公共停车场(){
clearScan();
断开连接();
}
公共无效停止扫描(){
clearScan();
}
公共空间断开连接(){
clearConnection();
clearNotification();
clearWrite();
clearKeepAwaken();
}
公共无效startScan(){
clearScan();
木材d(“开始扫描”);
scanSubscription=可观测计时器(3,时间单位:秒)
.flatMap(已忽略->rxBleClient.scanBleDevices())
.filter(rxBleScanResult->CommonUtils.isStormSensor(rxBleScanResult.getBleDevice())
.observeOn(AndroidSchedulers.mainThread())
.订阅(RXbleCanResult->{
RxBleDevice=rxBleScanResult.getBleDevice();
.d(“设备%s”,设备.getMacAddress());
if(device.getMacAddress()!=null&&!storageManager.containsDiscoveredDevice(device.getMacAddress())){
d(“找到设备%s%s”、设备.getName()、设备.getMacAddress());
storageManager.AddDiscoverySensor(device.getMacAddress(),device.getName());
EventBus.getDefault().post(发现新设备(device.getMacAddress(),device.getName());
}
storageManager.SetSensorConnectable(device.getMacAddress()、Calendar.getInstance().getTime());
},此::onblefilure);
}
公共无效连接设备(字符串macAddress、字符串门){
断开连接();
connectedDevice=rxBleClient.getBleDevice(macAddress);
if(connectedDevice!=null){
Timber.d(“开始连接到%s”,macAddress);
connectionSubscription=connectedDevice.establishConnection(上下文,false)
.订阅(连接->{
//由于传感器处理器的限制,需要延迟写入操作
writeCharacteristic(连接,CommonUtils.getBleTime())
.delay(AppConstants.BLUETOOTH\u WRITE\u delay\u MILIS,时间单位为毫秒);
writeCharacteristic(连接、应用常量、蓝牙设置、蜂鸣器关闭)
.delay(AppConstants.BLUETOOTH\u WRITE\u delay\u MILIS,时间单位为毫秒);
writeCharacteristic(连接、AppConstants.BLUETOOTH\u设置\u掩码)
.delay(AppConstants.BLUETOOTH\u WRITE\u delay\u MILIS,时间单位为毫秒);
writeCharacteristic(连接、AppConstants.BLUETOOTH\u CLEAR\u统计信息)
.delay(AppConstants.BLUETOOTH\u WRITE\u delay\u MILIS,时间单位为毫秒);
writeCharacteristic(连接、AppConstants.BLUETOOTH\u CLEAR\u MEM)
.delay(AppConstants.BLUETOOTH\u WRITE\u delay\u MILIS,时间单位为毫秒);
writeCharacteristic(连接、门)
.delay(AppConstants.BLUETOOTH\u WRITE\u delay\u MILIS,时间单位为毫秒);
writeCharacteristic(连接、应用常量、蓝牙\u清除\u掩码)
.delay(AppConstants.BLUETOOTH\u WRITE\u delay\u MILIS,时间单位为毫秒);
writeCharacteristic(连接、AppConstants.BLUETOOTH\u设置\u掩码)
.delay(AppConstants.BLUETOOTH\u WRITE\u delay\u MILIS,时间单位为毫秒);
activeConnection=连接;
getBasicParams(连接、macAddress);
订阅通知(连接、macAddress);
},可丢弃->{
Timber.e(“连接时出错”+throwable.toString());
handleConnectionError(macAddress);
断开连接();
});
}
}
公共无效写入门(字符串门){
clearWrite();
writeSubscription=Observable.CombineTest(
writeCharacteristic(activeConnection、AppConstants.BLUETOOTH\u CLEAR\u STATS)
.delay(AppConstants.BLUETOOTH\u WRITE\u delay\u MILIS,时间单位为.毫秒),
writeCharacteristic(activeConnection、AppConstants.BLUETOOTH\u CLEAR\u MEM)
.delay(AppConstants.BLUETOOTH\u WRITE\u delay\u MILIS,时间单位为.毫秒),
writeCharacteristic(活动连接、门)
.delay(AppConstants.BLUETOOTH\u WRITE\u delay\u MILIS,时间单位为.毫秒),
写特征(activeC)