我正在开发一个必须与BLE设备连接的应用程序,在我的代码中,我想使用从API 21(Android 5)实现的新的Scan和ScanCallback for BLE,但我必须保持与Android 4.3及更高版本的兼容性.
所以我用这种方式编写了代码:
if (Build.VERSION.SDK_INT >= 21) { mLEScanner.startScan(filters, settings, mScanCallback); } else { btAdapter.startLeScan(leScanCallback); }
我已经定义了2个回调,一个用于API 21及更高版本,另一个用于API 18到20:
//API 21 private ScanCallback mScanCallback = new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { BluetoothDevice btDevice = result.getDevice(); connectToDevice(btDevice); } public void connectToDevice(BluetoothDevice device) { if (mGatt == null) { mGatt = device.connectGatt(context, false, btleGattCallback); if (Build.VERSION.SDK_INT < 21) { btAdapter.stopLeScan(leScanCallback); } else { mLEScanner.stopScan(mScanCallback); } } } }; //API 18 to 20 private BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) { btAdapter.stopLeScan(leScanCallback); runOnUiThread(new Runnable() { @Override public void run() { mBluetoothGatt = device.connectGatt(context, false, btleGattCallback); } }); } };
我还添加了注释
@TargetApi(21)
但是当我在Android 4.x上启动应用程序时,它立即崩溃,报告无法找到类ScanCallback的错误(仅用于Android 5及更高版本的那个).
我怎么解决这个问题?
非常感谢你.丹尼尔.
看完几篇文章后,我做了以下几点.以防万一,这是关于BluetoothLe的Android文档
第一
创建两个方法之一scanLeDevice21
和scanLeDevice18
.在scanLeDevice21
添加注释时@RequiresApi(21)
说:
表示只应在给定API级别或更高级别上调用带注释的元素.这与旧的@TargetApi注释类似,但更清楚地表明这是调用者的要求,而不是用于在方法中"抑制"超过minSdkVersion的警告.
第二
实现每个方法,这是我的代码.
@RequiresApi(21) private void scanLeDevice21(final boolean enable) { ScanCallback mLeScanCallback = new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { super.onScanResult(callbackType, result); BluetoothDevice bluetoothDevice = result.getDevice(); if (!bluetoothDeviceList.contains(bluetoothDevice)) { Log.d("DEVICE", bluetoothDevice.getName() + "[" + bluetoothDevice.getAddress() + "]"); bluetoothDeviceArrayAdapter.add(bluetoothDevice); bluetoothDeviceArrayAdapter.notifyDataSetChanged(); } } @Override public void onBatchScanResults(Listresults) { super.onBatchScanResults(results); } @Override public void onScanFailed(int errorCode) { super.onScanFailed(errorCode); } }; final BluetoothLeScanner bluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner(); if (enable) { // Stops scanning after a pre-defined scan period. mHandler.postDelayed(() -> { mScanning = false; swipeRefreshLayout.setRefreshing(false); bluetoothLeScanner.stopScan(mLeScanCallback); }, SCAN_PERIOD); mScanning = true; bluetoothLeScanner.startScan(mLeScanCallback); } else { mScanning = false; bluetoothLeScanner.stopScan(mLeScanCallback); } } /** * Scan BLE devices on Android API 18 to 20 * * @param enable Enable scan */ private void scanLeDevice18(boolean enable) { BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(final BluetoothDevice bluetoothDevice, int rssi, byte[] scanRecord) { getActivity().runOnUiThread(new Runnable() { @Override public void run() { bluetoothDeviceArrayAdapter.add(bluetoothDevice); bluetoothDeviceArrayAdapter.notifyDataSetChanged(); } }); } }; if (enable) { // Stops scanning after a pre-defined scan period. mHandler.postDelayed(() -> { mScanning = false; mBluetoothAdapter.stopLeScan(mLeScanCallback); }, SCAN_PERIOD); mScanning = true; mBluetoothAdapter.startLeScan(mLeScanCallback); } else { mScanning = false; mBluetoothAdapter.stopLeScan(mLeScanCallback); } }
第三
每当您需要扫描设备时,您都会围绕代码询问您的版本.例如,我有一个RefreshLayout
显示设备列表.这是结果:
/** * Refresh listener */ private void refreshScan() { if (!hasFineLocationPermissions()) { swipeRefreshLayout.setRefreshing(false); //Up to marshmallow you need location permissions to scan bluetooth devices, this method is not here since is up to you to implement it and it is out of scope of this question. requestFineLocationPermission(); } else { swipeRefreshLayout.setRefreshing(true); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { scanLeDevice21(true); } else { scanLeDevice18(true); } } }
就是这样.
忘记扩展,子类化你并不真正需要的类,如ulusoyca的答案.