You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Pie中带ScanFilter的BLE后台扫描无法工作问题咨询

Android Pie 后台BLE扫描无法触发PendingBroadcast的解决方案

我之前踩过这个Android Pie的BLE后台扫描坑,Oreo及更早版本正常但Pie后台失效,核心原因是Android 9(API 28)对后台BLE扫描和位置权限的限制大幅收紧,结合你的代码,我整理了几个关键修复点:

1. 补全后台位置权限

Pie开始,后台进行BLE扫描必须持有位置权限,而且仅靠前台的ACCESS_COARSE_LOCATION/ACCESS_FINE_LOCATION不够,需要额外声明后台位置权限:

  • 在Manifest中添加:
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- 针对Pie的后台位置权限 -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" android:maxSdkVersion="28" />
  • 动态申请权限(在启动扫描前调用):
private static final int REQUEST_LOCATION_PERM = 1001;

private void checkLocationPermissions() {
    if (Build.VERSION.SDK_INT == Build.VERSION_CODES.P) {
        boolean hasFineLoc = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
        boolean hasCoarseLoc = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;
        if (!hasFineLoc || !hasCoarseLoc) {
            ActivityCompat.requestPermissions(this, 
                new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION},
                REQUEST_LOCATION_PERM);
        }
    }
}

2. 调整ScanSettings配置

你的代码用了SCAN_MODE_LOW_POWER,这种模式在Pie后台会被系统大幅限制扫描频率(甚至静止时停止扫描),建议换成SCAN_MODE_BALANCED,同时明确回调类型确保触发:

ScanSettings settings = new ScanSettings.Builder()
        .setScanMode(ScanSettings.SCAN_MODE_BALANCED)
        .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES) // 明确匹配时触发回调
        .build();

3. 修正PendingIntent的创建

Pie对PendingIntent的匹配逻辑更严格,建议给Intent添加明确的Action,避免系统无法匹配到你的BroadcastReceiver:

// 定义唯一的Action常量
private static final String ACTION_BLE_SCAN = "com.your.app.package.ACTION_BLE_SCAN";

// 创建Intent时指定Action
Intent intent = new Intent(this, MyBroadcastReceiver.class);
intent.setAction(ACTION_BLE_SCAN);
intent.putExtra("o-scan", true);

// 针对Pie及以上版本,确保Flag正确(Pie时还没有FLAG_IMMUTABLE,用UPDATE_CURRENT即可)
PendingIntent pendingIntent = PendingIntent.getBroadcast(
        this.getApplicationContext(),
        0,
        intent,
        PendingIntent.FLAG_UPDATE_CURRENT
);

4. 优化BroadcastReceiver的匹配逻辑

在Receiver中先校验Action,避免接收无关广播:

public class MyBroadcastReceiver extends BroadcastReceiver {
    private static final String ACTION_BLE_SCAN = "com.your.app.package.ACTION_BLE_SCAN";

    @Override
    public void onReceive(Context context, Intent intent) {
        // 先校验Action
        if (!ACTION_BLE_SCAN.equals(intent.getAction())) {
            return;
        }
        
        int bleCallbackType = intent.getIntExtra(BluetoothLeScanner.EXTRA_CALLBACK_TYPE, -1);
        if (bleCallbackType != -1) {
            Log.d(TAG, "Passive background scan callback type: "+bleCallbackType);
            ArrayList<ScanResult> scanResults = intent.getParcelableArrayListExtra(
                BluetoothLeScanner.EXTRA_LIST_SCAN_RESULT);
            // 处理ScanResult列表
        }
    }
}

额外注意点

  • 电池优化:Pie会对后台应用的电池优化更严格,建议把你的应用加入系统的「忽略电池优化」列表,否则扫描可能被系统暂停。
  • ScanFilter验证:暂时去掉ScanFilter测试是否能收到广播,如果能收到,说明你的Filter规则在Pie下有兼容性问题(比如UUID匹配格式、广播数据长度限制等),需要调整Filter逻辑。

内容的提问来源于stack exchange,提问作者Sathish Battula

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:26:47