0

我想在 ViewModel 中运行 BTLE 扫描。我不确定这是否是最好的方法,但对我来说这是一个很好的学习实验。在更简单的设置中运行扫描时,我确实成功地列出了我的 BT 设备。

权限BLUETOOTH BLUETOOTH_ADMINACCESS_COARSE_LOCATION设置在Manifest.

我的主要设置活动中有一个checkPermissions方法可以检查权限,并在需要时请求权限。我也有一个覆盖onRequestPermissionsResult。位置权限显示在我的应用程序的权限中。这些方法或多或少是开源项目的复制/粘贴(请参阅this)。

好吧,我的扫描不起作用。我的回调中的日志永远不会显示在我的日志中。没有错误,我在日志中看到的唯一可疑之处是:D/BluetoothLeScanner: onScannerRegistered() - status=0 scannerId=12 mScannerId=0.

我的 ViewModel 看起来像这样:

interface ScanningStatus {
    void setCurrentlyScanning(boolean updatedStatus);
    boolean getCurrentlyScanning();
}


public class SettingsScanningViewModel extends AndroidViewModel {
    private MutableLiveData<ArrayList<BluetoothDevice>> mDeviceList;
    private ArrayList<BluetoothDevice> mInternalDeviceList;
    private MutableLiveData<Boolean> mIsScanning;

    private static final String TAG = "viewmodel";

    private BluetoothManager mBtManager;
    private BluetoothAdapter mBtAdapter;
    private BluetoothLeScanner mBleScanner;
    private static final long SCAN_PERIOD = 5000;


    public SettingsScanningViewModel(Application mApplication) {
        super(mApplication);
        mDeviceList = new MutableLiveData<>();
        mInternalDeviceList = new ArrayList<>();
        mIsScanning = new MutableLiveData<>();

        mBtManager = (BluetoothManager) mApplication.getSystemService(Context.BLUETOOTH_SERVICE);
        mBtAdapter = mBtManager.getAdapter();
        mBleScanner = mBtAdapter.getBluetoothLeScanner();
    }


    MutableLiveData<ArrayList<BluetoothDevice>> getBtDevices() {
        return mDeviceList;
    }


    MutableLiveData<Boolean> getScanningStatus() {
        return mIsScanning;
    }


    private void flushList() {
        mInternalDeviceList.clear();
        mDeviceList.setValue(mInternalDeviceList);
    }


    private void injectIntoList(BluetoothDevice btDevice) {
        mInternalDeviceList.add(btDevice);
        mDeviceList.setValue(mInternalDeviceList);
    }


    private ScanCallback scanCallback = new ScanCallback() {
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            Log.d(TAG, "in callback");
            BluetoothDevice mDevice = result.getDevice();
            if (!mInternalDeviceList.contains(mDevice) && mDevice.getName() != null) {
                injectIntoList(mDevice);
            }
        }

        @Override
        public void onScanFailed(int errorCode) {
            Log.d(TAG, "onScanFailed: " + errorCode);
        }
    };


    private ScanningStatus scanningStatus = new ScanningStatus() {
        @Override
        public void setCurrentlyScanning(boolean status) {
            mIsScanning.setValue(status);
        }

        public boolean getCurrentlyScanning() {
            return mIsScanning.getValue();
        }
    };


    void doBtScan() {
        Log.d(TAG, "flush list first");
        flushList();
        Log.d(TAG, "starting scan with scanCallback " + scanCallback);
        scanningStatus.setCurrentlyScanning(true);
        mBleScanner.startScan(scanCallback);
        Log.d(TAG, "scan should be running for " + SCAN_PERIOD);

        Handler handler = new Handler();
        handler.postDelayed(() -> {
            mBleScanner.stopScan(scanCallback);
            scanningStatus.setCurrentlyScanning(false);
            }, SCAN_PERIOD);
    }
}

我真的不确定出了什么问题。是因为我正在创建新BluetoothManager的 ,BluetoothAdapter并且BluetoothLeScanner在我的 ViewModel 中与我发起和请求权限的主要活动相比?如果是这样,我怎么能重复使用这些相同的对象?

谢谢你。

4

2 回答 2

0

这三个步骤对我有用。

  1. GPS 应该打开(如果尚未打开,请编写一些代码将其打开)。

  2. ACCESS_COARSE_LOCATION 和 ACCESS_FINE_LOCATION 权限都应该在清单中声明并在运行时询问。

  3. 最重要的是以下关于 ScanSettings 的答案

https://stackoverflow.com/a/53831870/10432212

于 2021-01-30T13:09:47.873 回答
0

OKKKKKKKKKKKK 另一个例子,试图找出问题所在几个小时,发布,然后 200 万之后我自己才发现。

看起来ACCESS_COARSE_LOCATION还不够,ACCESS_FINE_LOCATION还需要。所以我想我必须使用与以前不同的 SDK!

谢谢你。

于 2020-07-27T13:01:00.690 回答