startLeScan replacement to current api

2019-02-03 08:24发布

问题:

Goal is to read the values of a bluetooth LE heart rate monitor.

Using google's sample, I get

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

        mScanning = true;
        mBluetoothAdapter.startLeScan(mLeScanCallback);
    } else {
        mScanning = false;
        mBluetoothAdapter.stopLeScan(mLeScanCallback);
    }
}

which causes mBluetoothAdapter.stopLeScan to be shown as deprecated. Startscan is no method of mBluetoothAdapter though.

How to change this for it to work with the current API?

回答1:

Both methodsBluetoothAdapter.startLeScan and BluetoothAdapter.stopLeScan were deprecated in Android Lollipop. As a replacement BluetoothLeScanner were introduced and acting as a scan controller.

If you develop BLE-based application you should control either scan via the BluetoothAdapter (Android 4.3 and Android 4.4) or the BluetoothLeScanner. The API introduced in Android Lollipop offers much greater features in terms of battery power consumption.



回答2:

Thank you all for your responses. To Summarize the answer to this question I'll add my final code snippet.

private BluetoothAdapter mBluetoothAdapter;


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

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

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

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    BluetoothManager bluetoothManager = (BluetoothManager) getActivity().getSystemService(Context.BLUETOOTH_SERVICE);
    mBluetoothAdapter = bluetoothManager.getAdapter();
}


private void scanLeDevice(final boolean enable) {

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


回答3:

Use BluetoothAdapter.getBluetoothLeScanner() to get an instance of BluetoothLeScanner.

Then, you can start or stop a scan with the startScan or stopScan methods, much like the deprecated version.

Difference is you can pass scanfilters and settings. The ScanCallback has more info about found devices. Filters allow you to filter scanresults based on name, macaddress, service UUIDs etc. Scan settings allow you to control scanning power.



回答4:

Remember that the method:

public BluetoothLeScanner getBluetoothLeScanner ()

isn't static. If you do:

BluetoothAdapter.getBluetoothLeScanner() 

you will get an error, since getDefaultAdapter() is a static method, but getBluetoothLeScanner() isn't.

You need an instance of a BluetoothAdapter. You can get one by doing:

(BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE).getAdapter()

That way, you can try:

Context mContext = getBaseContext();
BluetoothAdapter mAdapter = ((BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE)).getAdapter();
BluetoothLeScanner mLeScanner = mAdapter.getBluetoothLeScanner();

mLeScanner.startScan(...);

More info here: http://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html



回答5:

To avoid the warning. Just check API version before call the function. You can use the code

private BluetoothAdapter bluetoothAdapter;
private BluetoothAdapter.LeScanCallback leScanCallback;
private BluetoothAdapter.LeScanCallback leScanCallback;
private ScanCallback scanCallback;
private ScanSettings scanSetting;

// Check before call the function
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            bluetoothAdapter.getBluetoothLeScanner().startScan(filterList, scanSetting, scanCallback);
        } else {
            bluetoothAdapter.startLeScan(leScanCallback);
        }