vivo与Poco设备屏幕关闭时BLE扫描暂停问题求助
问题描述
我正在开发一个项目,需要持续启动BLE扫描接收Beacon设备的SOS消息,要求应用被杀死后扫描仍能保持活跃。当前实现方案如下:
前台服务配置
使用connectedDevice类型的前台服务:
<service android:name=".ui.service.BeaconForegroundService" android:foregroundServiceType="connectedDevice" android:exported="false"/>
BLE扫描实现
通过PendingIntent方式启动扫描:
fun startScanBluetoothDevice(pendingIntent: PendingIntent) { MyLogger.w(msg = "Scanning started !") val builder = ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) scanner = bluetoothAdapter?.bluetoothLeScanner scanner?.let { it.startScan(getScanFilter(), builder.build(), pendingIntent) } }
PendingIntent创建
val intent = Intent(context, BleScanReceiver::class.java) val pendingIntent = PendingIntent.getBroadcast( context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE )
扫描结果监听
用广播接收器接收扫描结果:
@AndroidEntryPoint class BleScanReceiver : BroadcastReceiver() { @Inject lateinit var bleManager: BleManager override fun onReceive(context: Context, intent: Intent) { MyLogger.d(msg = intent.toString()) } }
已确认事项
- 关闭了设备所有电池优化
- 获取了所有必要权限,蓝牙处于开启状态
- 严格遵循Android官方文档实现
问题现象
功能在摩托罗拉设备上正常,但在vivo和Poco设备上出现异常:屏幕关闭时BLE扫描暂停,无结果返回;屏幕点亮后扫描恢复正常。
屏幕关闭时日志(无扫描结果)
D Result Come : ScanResult{device=XX:XX:XX:XX:C8:98, scanRecord=ScanRecord [mAdvertiseFlags=6, mServiceUuids=[0000fff1-0000-1000-8000-00805f9b34fb], mServiceSolicitationUuids=[], mManufacturerSpecificData={}, mServiceData={00000000-0000-1000-8000-00805f9b34fb=[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -59, 97]}, mTxPowerLevel=-2147483648, mDeviceName=null, mTDSData=null, mTransportDiscoveryData=null], rssi=-47, timestampNanos=154178666809128, eventType=27, primaryPhy=1, secondaryPhy=0, advertisingSid=255, txPower=127, periodicAdvertisingInterval=0} 2026-04-22 12:00:50.682 14072-14072 VRI[MainActivity] com.uffizio.androidbledemo D visibilityChanged oldVisibility=true newVisibility=false 2026-04-22 12:00:50.772 14072-14072 ViewRootImpl com.uffizio.androidbledemo D AppSizeAfterRelayout, size: Point(720, 1612), rotation: ROTATION_0 2026-04-22 12:00:50.775 14072-14072 BLASTBufferQueue com.uffizio.androidbledemo D [VRI[MainActivity]#3](f:0,a:4) destructor() 2026-04-22 12:00:50.775 14072-14072 BufferQueueConsumer com.uffizio.androidbledemo D [VRI[MainActivity]#3(BLAST Consumer)3](id:36f800000003,api:0,p:-1,c:14072) disconnect
屏幕点亮时日志(扫描结果正常返回)
D Intent { flg=0x10 cmp=com.uffizio.androidbledemo/.ble_new.broadcast.BleScanReceiver (has extras) } 2026-04-22 12:02:19.097 14072-14072 AppFlow com.uffizio.androidbledemo D Bundle[mParcelledData.dataSize=440] Intent { flg=0x10 cmp=com.uffizio.androidbledemo/.ble_new.broadcast.BleScanReceiver (has extras) } 2026-04-22 12:02:19.097 14072-14072 AppFlow com.uffizio.androidbledemo D type : 1 2026-04-22 12:02:19.097 14072-14072 AppFlow com.uffizio.androidbledemo D [ScanResult{device=XX:XX:XX:XX:C8:98, scanRecord=ScanRecord [mAdvertiseFlags=6, mServiceUuids=[0000ffe1-0000-1000-8000-00805f9b34fb], mServiceSolicitationUuids=[], mManufacturerSpecificData={}, mServiceData={0000ffe1-0000-1000-8000-00805f9b34fb=[-95, 8, 97, -20, 65, -40, 105, -56, -104, 80, 76, 85, 83]}, mTxPowerLevel=-2147483648, mDeviceName=null, mTDSData=null, mTransportDiscoveryData=null], rssi=-43, timestampNanos=154272727111903, eventType=27, primaryPhy=1, secondaryPhy=0, advertisingSid=255, txPower=127, periodicAdvertisingInterval=0}]
解决方案
vivo、Poco这类国内定制ROM有严格的后台行为限制,即使关闭电池优化,系统仍可能在熄屏时暂停非核心任务。试试下面这些优化手段:
1. 强化前台服务优先级
- 给前台服务同时添加
connectedDevice和location类型(部分ROM会把BLE扫描归为位置相关行为,多类型声明能提升服务优先级):
<service android:name=".ui.service.BeaconForegroundService" android:foregroundServiceType="connectedDevice|location" android:exported="false"/>
- 启动前台服务时,必须调用
startForeground()并显示明确的持续通知,比如标注“正在监听Beacon SOS消息”——部分ROM会根据通知内容判断服务是否为用户需要的核心功能,以此决定是否放行后台运行。
2. 优化BLE扫描配置
- 调整扫描参数,确保系统不会节流扫描回调:
val builder = ScanSettings.Builder() .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES) // 接收所有匹配结果 .setNumOfMatches(ScanSettings.MATCH_NUM_MAX_ADVERTISEMENT) // 最大化匹配次数 .setReportDelay(0) // 立即返回结果
- Android 12+版本,若
BLUETOOTH_SCAN权限不需要关联位置,添加neverForLocation标记,避免被位置权限的节流机制影响:
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation"/>
3. 引导用户开启定制ROM特殊权限
这类设备仅靠代码配置无法绕过系统限制,必须引导用户手动开启:
- vivo设备:
- 开启「后台高耗电权限」:设置 -> 电池 -> 后台高耗电 -> 允许你的应用后台高耗电
- 开启「自启动权限」:设置 -> 应用与权限 -> 权限管理 -> 自启动 -> 允许你的应用自启动
- Poco(MIUI)设备:
- 设置「无限制后台」:设置 -> 应用设置 -> 应用管理 -> 找到你的应用 -> 省电策略 -> 无限制
- 开启「自启动权限」:设置 -> 应用设置 -> 应用管理 -> 找到你的应用 -> 自启动 -> 允许自启动
- 可以在应用内添加引导页面,通过Intent直接跳转至应用权限设置页:
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) intent.data = Uri.fromParts("package", context.packageName, null) context.startActivity(intent)
4. 备选:用WorkManager做周期性扫描兜底
如果前台服务还是被系统拦截,试试用WorkManager创建周期性任务,每次任务启动时执行一次BLE扫描(注意控制扫描时长,避免被判定为恶意耗电):
val scanWorkRequest = PeriodicWorkRequestBuilder<BleScanWorker>(15, TimeUnit.MINUTES) .setConstraints(Constraints.Builder() .setRequiresBleConnected(false) .setRequiredNetworkType(NetworkType.NOT_REQUIRED) .build()) .build() WorkManager.getInstance(context).enqueueUniquePeriodicWork( "BLE_SCAN_TASK", ExistingPeriodicWorkPolicy.REPLACE, scanWorkRequest )
在BleScanWorker内部实现扫描逻辑,扫描完成后主动结束任务。
5. 检查广播接收器有效性
- 确保广播接收器在Manifest中正确注册,并且开启
exported和enabled:
<receiver android:name=".ble_new.broadcast.BleScanReceiver" android:exported="true" android:enabled="true"/>
- 也可以尝试在前台服务内部动态注册广播接收器,避免Manifest注册被系统拦截。
内容的提问来源于stack exchange,提问作者Aditya_Giri
相关产品推荐
相关产品推荐

