在低功耗蓝牙(BLE)开发过程中碰到过不少坑,作为记录总结一下在开发过程中关于开启扫描遇到的问题。
开发低功耗蓝牙过程中因为Android系统的不断升级和优化,关于BLE的开发也会在升级过程中遇到不同的问题。关于开启扫描问题总结如:
-
在开发过程中关闭扫描后再开启扫描不成功问题
在开发过程中不可避免的会遇到关闭扫描开启扫描如此重复操作的问题,但在某些时候会出现关闭后无法再开启扫描的问题。
E/BtGatt.GattService: App 'com.bluetooth.app' is scanning too frequently
这时问题就是你开启扫描功能太频繁了,导致系统吃不消导致的,遇到这种情况你需要在关闭扫描之后至少停止2秒钟,然后再次调用开启扫描方法,开启成功。
-
在Android 6.0及以上版本中开启蓝牙扫描后扫描不到数据问题
在Android 6.0之前的版本中能够完美运行,但换到Android 6.0 及以上系统的手机运行时搜索不到数据。
这是因为在Android 6.0及以上系统中低功耗蓝牙添加了距离检测功能,所以扫描时需要开启定位功能权限,在更高版本中甚至需要开启精准定位权限
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
在代码中也需要申请动态权限
//清单文件里面也需要配置
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED ) {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION ,
Manifest.permission.CAMERA,}, PERMISSIONS_REQUEST_CODE_ACCESS);
}
把各种权限问题解决之后,在Android 6.0之前扫描没问题,在之后扫描不到数据问题也随之解决
-
Android 8.1及以上系统后台模式无法开启扫描问题
在Android 8.1 及以上系统中,正常状况下扫描蓝牙没有问题,但是当App处于后台时,无法开启扫描方法并有如下提示
BtGatt.ScanManager: Cannot start unfiltered scan in screen-off. This scan will be resumed later: 9
这是因为你开启的扫描扫描方法是没有设置扫描过滤器的问题,在Android 8.1及以上系统中在后台模式中开启扫描必须要关联扫描过滤器,如此才能在后台模式下完美运行
//设置蓝牙扫描过滤器集合
private List<ScanFilter> scanFilterList;
//设置蓝牙扫描过滤器
private ScanFilter.Builder scanFilterBuilder;
//设置蓝牙扫描设置
private ScanSettings.Builder scanSettingBuilder;
private List<ScanFilter> buildScanFilters() {
scanFilterList = new ArrayList<>();
// 通过服务 uuid 过滤自己要连接的设备 过滤器搜索GATT服务UUID
scanFilterBuilder = new ScanFilter.Builder();
ParcelUuid parcelUuidMask = ParcelUuid.fromString("FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF");
ParcelUuid parcelUuid = ParcelUuid.fromString("00001800-0000-1000-8000-00805f9b34fb");
scanFilterBuilder.setServiceUuid(parcelUuid, parcelUuidMask);
scanFilterList.add(scanFilterBuilder.build());
return scanFilterList;
}
private ScanSettings buildScanSettings() {
scanSettingBuilder = new ScanSettings.Builder();
//设置蓝牙LE扫描的扫描模式。
//使用最高占空比进行扫描。建议只在应用程序处于此模式时使用此模式在前台运行
scanSettingBuilder.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY);
//设置蓝牙LE扫描滤波器硬件匹配的匹配模式
//在主动模式下,即使信号强度较弱,hw也会更快地确定匹配.在一段时间内很少有目击/匹配。
scanSettingBuilder.setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE);
//设置蓝牙LE扫描的回调类型
//为每一个匹配过滤条件的蓝牙广告触发一个回调。如果没有过滤器是活动的,所有的广告包被报告
scanSettingBuilder.setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES);
return scanSettingBuilder.build();
}
//调用开启扫描方法
mBluetoothAdapter.getBluetoothLeScanner().startScan(buildScanFilters(), buildScanSettings(), mLeScanCallback);
根据实际情况设置相应的参数设置,调用添加过滤设置和扫描设置的扫描方法,即在后台状态下依然可以开启扫描功能。
通过本文记录一下在开发过程中遇到的开启扫描在不同版本中遇到的问题及解决方法。