AndroidTV开机自启BLE前台服务无法返回扫描结果问题
Android 10 AndroidTV 开机自启BLE扫描无结果问题
问题概述
搭载Android 10的AndroidTV设备上,应用的前台服务用于持续扫描指定MAC地址的BLE设备。从启动器启动应用时扫描正常,但设备重启后通过BOOT_COMPLETED广播启动服务时,即便BLE设备在范围内,扫描结果始终为空;后续打开应用重启扫描器后恢复正常。
相关代码
BLE扫描实现
import no.nordicsemi.android.support.v18.scanner.BluetoothLeScannerCompat import no.nordicsemi.android.support.v18.scanner.ScanCallback import no.nordicsemi.android.support.v18.scanner.ScanFilter import no.nordicsemi.android.support.v18.scanner.ScanResult import no.nordicsemi.android.support.v18.scanner.ScanSettings fun scan() { BluetoothLeScannerCompat.getScanner() .startScan( /* MAC地址过滤规则 */ filters, ScanSettings.Builder() .setLegacy(false) .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) .setUseHardwareBatchingIfSupported(false) .setReportDelay(5000) .build(), /* 扫描回调 */ callback ) }
启动器启动服务(MainActivity)
override fun onCreate(savedInstanceState: Bundle?) { // ... UI逻辑 ... startForegroundService(Intent(this, BleService::class.java)) }
开机广播接收器
class BootCompletedReceiver: BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { if (intent?.action == Intent.ACTION_BOOT_COMPLETED) { context?.startForegroundService(Intent(context, BleService::class.java)) } } }
日志信息
BluetoothAdapter D isLeEnabled(): ON BluetoothLeScanner D onScannerRegistered() - status=0 scannerId=5 mScannerId=0 BluetoothScanJob I Start Scan BluetoothS...b$callback I [onBatchScanResults]: Results=[]
已确认事项
- 两种启动方式下,服务均能正常初始化并启动扫描器,无报错
- LogCat稳定输出
onScannerRegistered()确认信息 BOOT_COMPLETED广播触发正常,无延迟或丢失- 服务启动与扫描初始化之间添加20秒延迟无效果
- 是否设置
reportDelay不影响扫描结果 - 已配置所有必要的清单权限及运行时权限
清单文件内容
<manifest <!-- 省略其他配置 --> > <!-- 省略其他权限 --> <!-- SDK 30及以下蓝牙权限 --> <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" /> <!-- SDK 30以上蓝牙权限 --> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/> <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" tools:targetApi="31" /> <!-- 前台服务权限 --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE"/> <!-- 开机自启权限 --> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <!-- 强制要求BLE硬件支持 --> <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/> <application <!-- 省略其他配置 --> > <receiver android:name=".service.BootCompletedReceiver" android:exported="true"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver> <service android:name=".service.BleService" android:label="@string/service_name" android:description="@string/service_description" android:exported="false" android:foregroundServiceType="connectedDevice"/> <activity android:name=".ui.main.MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <provider android:name="androidx.startup.InitializationProvider" android:authorities="${applicationId}.androidx-startup" tools:node="remove"> </provider> </application> </manifest>
解决方案尝试
1. 强制重置BLE适配器
Android 10 TV设备开机后,BLE可能处于“已启用”但底层未就绪状态。尝试重置BLE后再启动扫描:
val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter() if (bluetoothAdapter.isLeEnabled) { bluetoothAdapter.disableLe() Handler(Looper.getMainLooper()).postDelayed({ bluetoothAdapter.enableLe() Handler(Looper.getMainLooper()).postDelayed({ scan() }, 2000) }, 1000) } else { bluetoothAdapter.enableLe() Handler(Looper.getMainLooper()).postDelayed({ scan() }, 2000) }
2. 调整扫描模式
SCAN_MODE_LOW_LATENCY在开机初期系统资源紧张时可能无法正常工作,切换为平衡模式:
ScanSettings.Builder() .setLegacy(false) .setScanMode(ScanSettings.SCAN_MODE_BALANCED) // 修改扫描模式 .setUseHardwareBatchingIfSupported(false) .setReportDelay(5000) .build()
3. 临时移除MAC过滤
开机后蓝牙底层可能无法正确处理MAC地址过滤规则,先扫描所有设备确认能获取结果后再添加过滤:
BluetoothLeScannerCompat.getScanner() .startScan( null, // 临时移除过滤规则 scanSettings, callback )
4. 确保前台服务通知正确创建
Android 10要求前台服务必须在启动后5秒内显示通知,否则会被系统限制。在BleService的onStartCommand中确保调用startForeground():
private val CHANNEL_ID = "ble_scan_channel" private val NOTIFICATION_ID = 1001 override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { // 创建通知渠道(Android O及以上要求) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel(CHANNEL_ID, "BLE扫描服务", NotificationManager.IMPORTANCE_LOW) val notificationManager = getSystemService(NotificationManager::class.java) notificationManager.createNotificationChannel(channel) } // 构建前台通知 val notification = NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle(getString(R.string.service_name)) .setContentText(getString(R.string.service_description)) .setSmallIcon(R.drawable.ic_notification) .build() // 启动前台服务 startForeground(NOTIFICATION_ID, notification) // 初始化扫描 scan() return START_STICKY }
5. 监听蓝牙完全就绪状态
注册蓝牙状态广播,确保在蓝牙完全进入STATE_ON状态后再启动扫描:
class BleService : Service() { private val bluetoothStateReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { val state = intent?.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR) if (state == BluetoothAdapter.STATE_ON) { // 蓝牙完全就绪,启动扫描 scan() // 取消注册广播避免重复触发 unregisterReceiver(this) } } } override fun onCreate() { super.onCreate() // 注册蓝牙状态监听广播 val filter = IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED) registerReceiver(bluetoothStateReceiver, filter) } override fun onDestroy() { super.onDestroy() unregisterReceiver(bluetoothStateReceiver) } }
内容的提问来源于stack exchange,提问作者Thijs
相关产品推荐
相关产品推荐

