android BTLE扫描回调似乎未被调用

huangapple 未分类评论60阅读模式
英文:

android BTLE scan callback seemingly not called

问题

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

在 Manifest 中设置了权限 BLUETOOTHBLUETOOTH_ADMINACCESS_COARSE_LOCATION

在我的主设置活动中,我有一个 checkPermissions 方法,用于检查权限,并在需要时请求权限。我还重写了 onRequestPermissionsResult。位置权限显示在我的应用程序的权限中。这些方法或多或少是从开源项目中复制/粘贴来的(参见这里)。

所以嗯,我的扫描不起作用。在我的回调中,日志从未显示在我的日志中。没有错误,我在日志中唯一可疑的事情是这个:D/BluetoothLeScanner: onScannerRegistered() - status=0 scannerId=12 mScannerId=0

我的 ViewModel 如下:

// ViewModel 代码

我真的不确定出了什么问题。是不是因为我在 ViewModel 中创建了新的 BluetoothManagerBluetoothAdapterBluetoothLeScanner,而与主活动在哪里初始化和请求权限?如果是这样,我如何重新使用这些相同的对象?

谢谢。

英文:

I want to run a BTLE scan within a ViewModel. I'm not sure if this is the best approach but it is a good learning experiment for me. I did manage to successfully list my BT devices when running the scan in a more simple setup.

Permissions BLUETOOTH BLUETOOTH_ADMIN and ACCESS_COARSE_LOCATION are set in the Manifest.

I have a checkPermissions method in my main settings activity that checks for permissions, and requests permissions if needed. I also have an override for onRequestPermissionsResult. The location permissions shows in my app's permissions. Those methods are more or less a copy/paste of open-source projects (see this).

So well, my scan doesn't work. The log in my callback never shows in my logs. There is no error, the only suspicious thing I'm seeing in the logs is this: D/BluetoothLeScanner: onScannerRegistered() - status=0 scannerId=12 mScannerId=0.

My ViewModel looks like this:

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);
    }
}

I am really not sure what is wrong. Is it because I'm creating new BluetoothManager, BluetoothAdapter and BluetoothLeScanner in my ViewModel compared with the main activity where I initiate and request permissions? If so, how could I re-use these same objects?

Thank you.

答案1

得分: 0

好的,以下是翻译好的内容:

OKKKKKKKKKKKK 又一个尝试了几个小时试图找出问题所在,发帖,然后2分钟后自己找到了。

看起来 ACCESS_COARSE_LOCATION 还不够,需要 ACCESS_FINE_LOCATION。所以我想我一定在使用不同的 SDK!

谢谢。

英文:

OKKKKKKKKKKKK another instance of trying to find out what's wrong for hours, posting, then 2mn later finding out by myself.

Looks like ACCESS_COARSE_LOCATION is not enough and ACCESS_FINE_LOCATION is needed. So I suppose I must be using a different SDK than previously!

Thank you.

答案2

得分: 0

这三个步骤对我有效。

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

  2. 在清单中声明ACCESS_COARSE_LOCATION和ACCESS_FINE_LOCATION权限,并在运行时进行请求。

  3. 最重要的是下面这个关于ScanSettings的答案:

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

英文:

These three steps worked for me.

  1. GPS should be turned on (write some code to turn it on if not already).

  2. both ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION permissions should be declared in manifest and asked at runtime.

  3. and the most important is the below answer talking about ScanSettings

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

huangapple
  • 本文由 发表于 2020年7月27日 20:54:04
  • 转载请务必保留本文链接:https://java.coder-hub.com/63115770.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定