Android蓝牙低功耗(BLE)设备扫描应用程序从不执行ScanCallback

时间:2019-05-19 19:24:28

标签: java android bluetooth-lowenergy

我正在开发的应用程序的功能之一涉及与​​启用BLE的设备进行数据同步。

我正在一个单独的应用程序中开发蓝牙功能(可以在下面的代码中看到),并且一旦工作即可将其包含在主应用程序中。

我的问题与BLE设备的扫描有关。当我执行代码时,它永远不会执行LE ScanCallback,因此我显然无法继续传输数据等。

我已阅读https://developer.android.com/guide/topics/connectivity/bluetooth-le上的Android开发人员文档,并且在Stack Overflow上也阅读了类似的问题,例如Android BLE- How is onScanResult method being called in ScanCallback?上的这个问题,但没有成功。

运行该应用程序的设备具有Android版本9(API 28),并且我确定范围内的BLE设备是可发现的(我已经与其他应用程序进行了检查,并内置了蓝牙搜索功能。)

在清单中,我已授予BLUETOOTHBLUETOOTH_ADMINACCESS_FINE_LOCATIONACCESS_COARSE_LOCATION的权限。我确保在运行代码时启用了我的位置信息,所有信息都不会出现。

public class MainActivity extends AppCompatActivity {

    private static final int REQUEST_ENABLE_BT = 0;
    private static final int REQUEST_DISCOVERABLE_BT = 0;
    private static final long SCAN_PERIOD = 20000;
    private String TAG = "Tag: ";

    private BluetoothAdapter mBluetoothAdapter;
    private boolean mScanning;
    private Handler mHandler;

    private ArrayList<BluetoothDevice> mScannedDevices;

    private ScanCallback mLeScanCallback = new ScanCallback() {
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            super.onScanResult(callbackType, result);

            System.out.println("BLE// onScanResult");
            Log.i("callbackType", String.valueOf(callbackType));
            Log.i("result", result.toString());
            Log.i("Device Name: ", result.getDevice().getName());

            BluetoothDevice btDevice = result.getDevice();
            mScannedDevices.add(btDevice);
        }

        @Override
        public void onBatchScanResults(List<ScanResult> results) {
            super.onBatchScanResults(results);

            System.out.println("BLE// onBatchScanResults");
            for (ScanResult sr : results) {
                Log.i("ScanResult - Results", sr.toString());
            }
        }

        @Override
        public void onScanFailed(int errorCode) {
            super.onScanFailed(errorCode);

            System.out.println("BLE// onScanFailed");
            Log.e("Scan Failed", "Error Code: " + errorCode);
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Initialise variables
        mScannedDevices = new ArrayList<>();
        mHandler = new Handler();

        // Initializes Bluetooth adapter.
        final BluetoothManager bluetoothManager =
                (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = bluetoothManager.getAdapter();

        // Check if device supports Bluetooth
        if (mBluetoothAdapter == null) {
            Toast.makeText(this, "Device DOES NOT support Bluetooth", Toast.LENGTH_LONG).show();
            // Disable bluetooth interactivity
            // ...
        } else {
            Toast.makeText(this, "Device DOES support Bluetooth", Toast.LENGTH_LONG).show();
        }

    }

    public void btOn(View v) {
        // Enable Bluetooth
        if (!mBluetoothAdapter.isEnabled()) {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
            Toast.makeText(this, "Turned on", Toast.LENGTH_LONG).show();
        } else {
            Toast.makeText(this, "Already on", Toast.LENGTH_LONG).show();
        }
    }

    public void btOff(View v) {
        mBluetoothAdapter.disable();
        Toast.makeText(getApplicationContext(), "Turned off", Toast.LENGTH_LONG).show();
    }

    public void btDiscoverable(View v) {
        Intent enableBTVisibility = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
        startActivityForResult(enableBTVisibility, REQUEST_DISCOVERABLE_BT);
    }

    public void btSearch(View v) {
        mScannedDevices.clear();
        scanLeDevice(true);
    }

    public void btStopSearch(View v) {
        scanLeDevice(false);
    }

    private void scanLeDevice(final boolean enable) {
        // Ensure Bluetooth and Location are on
        // ...

        // Bluetooth scanner object
        final BluetoothLeScanner bluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();

        if (enable) {
            // Stops scanning after a pre-defined scan period.
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    mScanning = false;
                    bluetoothLeScanner.stopScan(mLeScanCallback);
                }
            }, SCAN_PERIOD);

            mScanning = true;
            bluetoothLeScanner.startScan(mLeScanCallback);
        } else {
            mScanning = false;
            bluetoothLeScanner.stopScan(mLeScanCallback);
        }
    }

    @Override
    protected void onPause() {
        super.onPause();

        scanLeDevice(false);
        mScannedDevices.clear();
    }

}

我希望执行mLeScanCallback,但是永远不会执行(我已经在调试模式下检查了停止点,并且已经检查了日志)。

我以前从未在Android中使用过蓝牙,所以我担心我可能会误解它的工作原理。

1 个答案:

答案 0 :(得分:0)

确保您请求BLUETOOTH,BLUETOOTH_ADMIN权限以及ACCESS_COARSE_LOCATION或ACCESS_FINE_LOCATION权限。不幸的是,如果您不要求这些许可,则扫描只会自动失败。