startLeScan的替代方案和当前API相关。

39

目标是读取蓝牙低功耗心率监测器的值。

使用谷歌提供的示例代码,我得到了:

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

这导致mBluetoothAdapter.stopLeScan被标记为过时。但是mBluetoothAdapter没有startScan方法。

如何更改以使其与当前的API兼容?


7
一年后,同样的样本仍然被弃用,为什么他们不更新? - user3290180
好的,当我在谷歌工作时,我会保持文档更新。我之所以来到这里,是因为我也找不到如何做:p - Pedro Varela
5个回答

28

在Android Lollipop中,BluetoothAdapter.startLeScanBluetoothAdapter.stopLeScan这两种方法已被弃用。作为替代方案,引入了BluetoothLeScanner并作为扫描控制器。

如果您正在开发基于BLE的应用程序,则应通过BluetoothAdapter(Android 4.3和Android 4.4)或BluetoothLeScanner来控制扫描。在Android Lollipop中引入的API在电池功耗方面提供了更多功能。


我可以在 Android 4.3 中使用 BluetoothLeScanner 吗(使用 Lollipop 编译,但最小 SDK 设置为 18)? - Felix
4
在API 21以下的操作系统版本上无法使用BluetoothLeScanner。在这些设备上,Android SDK中将不会出现这个类。尝试对它们执行BLE扫描将导致抛出ClassNotFoundException异常。 - dawid gdanski

27

感谢大家的回复。为了总结这个问题的答案,我将添加我的最终代码片段。

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

11

使用BluetoothAdapter.getBluetoothLeScanner()方法获取一个BluetoothLeScanner的实例。

之后,你可以通过startScanstopScan方法启动或停止扫描,类似于废弃的版本。

不同之处在于,你可以传递扫描筛选器和设置。ScanCallback提供了有关已发现设备的更多信息。筛选器允许你根据名称、mac地址、服务UUID等过滤扫描结果。扫描设置允许你控制扫描功率。


使用 import android.bluetooth.BluetoothAdapter;,我只能获得 .getDefaultAdapter() 而无法获取 .getBluetoothLeScanner()。因此,我无法获得 startScan,只能使用已过时的方法。 - Vitalis Hommel
你的目标SDK设置为21了吗?并且你有一个BluetoothAdapter实例来获取BluetoothLeScanner吗? - JPS

6

请记住这个方法:

public BluetoothLeScanner getBluetoothLeScanner ()

不是静态的。如果你这样做:

BluetoothAdapter.getBluetoothLeScanner() 

如果使用 getDefaultAdapter() 方法,会出现错误,因为该方法是静态的,而 getBluetoothLeScanner() 不是。

你需要一个 BluetoothAdapter 实例。可以通过以下方式获取:

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

这样,您可以尝试:

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

mLeScanner.startScan(...);

更多信息请查看:http://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html

(此处为原文,无需翻译)

5
为了避免警告,请在调用函数之前检查API版本。您可以使用以下代码:
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);
        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接