android 蓝牙 setscanmode,蓝牙LE扫描在后台无法在Android M上运行

本文探讨了在Android M上使用ScanFilters时遇到的问题及解决方案。文中提到,在Android5.1.1上运行正常的应用在升级到Android6.0后出现无法接收到蓝牙设备回调的情况。文章详细解释了解决方案,即在运行时通过requestPermissions()方法请求用户授权。

以下代码适用于运行Android 5.1.1(Build LMY48M)的Nexus 9,但不适用于运行Android 6.0的Nexus 9(Build MPA44l)

List filters = new ArrayList();

ScanSettings settings = (new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_POWER)).build();

ScanFilter.Builder builder = new ScanFilter.Builder();

builder.setManufacturerData((int) 0x0118, new byte[]{(byte) 0xbe, (byte) 0xac}, new byte[]{(byte) 0xff, (byte)0xff});

ScanFilter scanFilter = builder.build();

filters.add(scanFilter);

mBluetoothLeScanner.startScan(filters, settings, new ScanCallback() {

...

});

在Android 5.x上,当看到与扫描过滤器匹配的制造商广告时,上述代码产生回调. (参见下面的示例Logcat输出.)在带有MPA44l的Nexus 9上,没有收到回调.如果您注释掉扫描过滤器,则会在Nexus 9上成功接收回调.

09-22 00:07:28.050 1748-1796/org.altbeacon.beaconreference D/BluetoothLeScanner﹕ onScanResult() - ScanResult{mDevice=00:07:80:03:89:8C, mScanRecord=ScanRecord [mAdvertiseFlags=6, mServiceUuids=null, mManufacturerSpecificData={280=[-66, -84, 47, 35, 68, 84, -49, 109, 74, 15, -83, -14, -12, -111, 27, -87, -1, -90, 0, 1, 0, 1, -66, 0]}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=null], mRssi=-64, mTimestampNanos=61272522487278}

有没有人看过ScanFilters在Android M上工作?

解决方法:

我的应用程序连接到蓝牙也有类似的问题.不是LE ScanFilter,但它就像OP一样是权限问题.

根本原因是从SDK 23开始,您需要使用Activity的requestPermissions()方法在运行时提示用户获取权限.

这对我有用:

>将以下两行之一添加到根节点内的AndroidManifest.xml中:

>在您的Activity中,在尝试连接到蓝牙之前,请调用Activity的requestPermissions()方法,该方法打开系统对话框以提示用户获取权限.权限对话框在另一个线程中打开,因此在尝试连接到蓝牙之前一定要等待结果.

>覆盖Activity的onRequestPermissionsResult()来处理结果.如果用户拒绝授予权限,该方法实际上只需要做一些事情,告诉用户应用程序无法进行蓝牙活动.

This blog post有一些示例代码,它使用AlertDialogs告诉用户发生了什么.这是一个很好的起点,但有一些缺点:

>它不处理等待requestPermissions()线程完成

>包含对requestPermissions()的调用的AlertDialog对我来说似乎是无关紧要的.对requestPermissions()的裸调用就足够了.

<think> 由于问题涉及安卓蓝牙扫描,我们需要考虑蓝牙扫描的基本流程以及可能影响扫描结果的参数。 在安卓中,使用BluetoothAdapter的startLeScan()方法(已弃用)或BluetoothLeScanner的startScan()方法进行蓝牙扫描扫描不到的可能原因及解决方案: 1. 权限问题:确保已经获取了必要的位置权限(在Android 6.0及以上,扫描蓝牙需要ACCESS_FINE_LOCATION或ACCESS_COARSE_LOCATION权限) 2. 扫描设置:可以通过调整扫描参数(ScanSettings)来增强扫描能力,例如设置扫描模式为低延迟模式。 3. 扫描过滤器:如果设置了过滤器,请确保过滤器正确,或者尝试不设置过滤器以查看是否能扫描到设备。 4. 蓝牙适配器状态:确保蓝牙已开启。 5. 设备支持:确保设备支持蓝牙4.0(BLE)。 6. 扫描时间:扫描时间太短可能导致未扫描到,可以延长扫描时间。 以下是一个使用BluetoothLeScanner进行扫描的示例代码,并设置了扫描参数(高功率、低延迟模式): </think> ### 安卓蓝牙扫描问题解决方案 在安卓系统中,蓝牙扫描失败通常由扫描参数配置不当、权限问题或硬件限制导致。以下是完整的解决方案: #### 关键修改参数及代码实现 ```java // 修改扫描参数的核心代码 BluetoothLeScanner scanner = bluetoothAdapter.getBluetoothLeScanner(); // 1. 创建扫描设置(关键参数调整) ScanSettings settings = new ScanSettings.Builder() .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) // 高扫描频率模式 .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES) // 接收所有结果 .setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE) // 积极匹配模式 .setNumOfMatches(ScanSettings.MATCH_NUM_MAX_ADVERTISEMENT) // 最大匹配数 .setReportDelay(0) // 立即报告结果 .build(); // 2. 创建扫描过滤器(可选,空列表表示接收所有设备) List<ScanFilter> filters = new ArrayList<>(); // 3. 开始扫描(API>=21) scanner.startScan(filters, settings, new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { // 处理扫描结果 BluetoothDevice device = result.getDevice(); Log.d("BLE", "发现设备: " + device.getName() + " | MAC: " + device.getAddress()); } @Override public void onScanFailed(int errorCode) { // 处理扫描失败 Log.e("BLE", "扫描失败,错误码: " + errorCode); } }); // 4. 停止扫描(10秒后停止示例) new Handler(Looper.getMainLooper()).postDelayed(() -> { scanner.stopScan(scanCallback); Log.i("BLE", "扫描已停止"); }, 10000); // 10秒后停止 ``` #### 关键参数说明: 1. **扫描模式 (`setScanMode`)**: - `SCAN_MODE_LOW_LATENCY` (最推荐):高频率扫描(≈每秒10次),耗电最高但成功率最高 - `SCAN_MODE_BALANCED`:平衡模式(≈每秒5次) - 避免使用`SCAN_MODE_LOW_POWER`(≈每秒1次)和`SCAN_MODE_OPPORTUNISTIC` 2. **匹配模式 (`setMatchMode`)**: - `MATCH_MODE_AGGRESSIVE`:积极匹配模式,减少过滤遗漏 - `MATCH_MODE_STICKY`:严格匹配,可能漏掉部分设备 3. **其他关键设置**: - `setReportDelay(0)`:立即上报扫描结果 - `setNumOfMatches(ScanSettings.MATCH_NUM_MAX_ADVERTISEMENT)`:接收最多广播包 #### 必须添加的权限(AndroidManifest.xml): ```xml <uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> <!-- Android 12+ 需要添加 --> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation"/> <!-- 如果不需要位置信息 --> <!-- 位置权限(Android 6.0+ 必须) --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> ``` #### 运行时权限检查(Android 6.0+): ```java // 在Activity中检查权限 private static final int REQUEST_ENABLE_BT = 1; private static final int PERMISSION_REQUEST_CODE = 2; public void checkPermissions() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { requestPermissions(new String[]{ Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.BLUETOOTH_SCAN // Android 12+ }, PERMISSION_REQUEST_CODE); } } } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { if (requestCode == PERMISSION_REQUEST_CODE) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 权限已授予,开始扫描 } } } ``` #### 常见问题排查: 1. **设备兼容性检查**: ```java // 检查设备是否支持BLE if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { Toast.makeText(this, "设备不支持BLE", Toast.LENGTH_SHORT).show(); } // 检查蓝牙是否开启 if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) { Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); } ``` 2. **过滤系统限制**: - Android 8.0+:后台扫描频率限制(前台应用不受影响) - Android 10+:MAC地址随机化(使用`device.getName()`识别设备) 3. **处理扫描错误**: ```java @Override public void onScanFailed(int errorCode) { switch (errorCode) { case ScanCallback.SCAN_FAILED_APPLICATION_REGISTRATION_FAILED: // 应用注册失败(重启蓝牙) case ScanCallback.SCAN_FAILED_INTERNAL_ERROR: // 内部错误(重启设备) case ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED: // 设备不支持 case ScanCallback.SCAN_FAILED_ALREADY_STARTED: // 重复扫描 } } ``` ### 优化建议: 1. **扫描周期**:每次扫描不超过10-15秒,间歇2秒后重启扫描 2. **设备过滤**:在`onScanResult`中通过名称或MAC地址过滤设备 3. **前台服务**:Android 8.0+在后台扫描需使用前台服务 4. **最新API**:使用`BluetoothLeScanner`代替弃用的`startLeScan()`
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值