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

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设备:
    1. 开启「后台高耗电权限」:设置 -> 电池 -> 后台高耗电 -> 允许你的应用后台高耗电
    2. 开启「自启动权限」:设置 -> 应用与权限 -> 权限管理 -> 自启动 -> 允许你的应用自启动
  • Poco(MIUI)设备:
    1. 设置「无限制后台」:设置 -> 应用设置 -> 应用管理 -> 找到你的应用 -> 省电策略 -> 无限制
    2. 开启「自启动权限」:设置 -> 应用设置 -> 应用管理 -> 找到你的应用 -> 自启动 -> 允许自启动
  • 可以在应用内添加引导页面,通过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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.01 17:27:26