Flutter/Android:应用被杀死后BLE Beacon监测功能失效
Android 13 后台杀死后BLE Beacon监测失效问题解决
问题核心原因
Android 13(API 33)对后台进程和位置权限的限制进一步收紧:
- 应用被杀死后进程完全销毁,
Application.onCreate()不会再执行,原有Beacon监测逻辑直接失效 - 普通后台扫描无法绕过系统省电机制,必须通过前台服务保持进程存活,同时申请必要的后台权限
具体解决方案
1. 补充Manifest权限声明
在AndroidManifest.xml中添加以下权限:
<!-- 基础蓝牙与位置权限 --> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <!-- Android 10+ 后台位置权限 --> <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> <!-- 前台服务相关 --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" /> <!-- 声明前台服务 --> <service android:name=".BeaconMonitoringService" android:foregroundServiceType="location" />
2. 请求运行时权限
必须主动请求前台位置权限和后台位置权限,否则后台扫描无法触发:
private const val PERMISSION_REQUEST_CODE = 1002 // 在Activity中发起权限请求 private fun requestRequiredPermissions() { val permissions = arrayOf( Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION ) ActivityCompat.requestPermissions(this, permissions, PERMISSION_REQUEST_CODE) } // 处理权限申请结果 override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == PERMISSION_REQUEST_CODE && grantResults.all { it == PackageManager.PERMISSION_GRANTED }) { // 权限全部通过,启动前台服务 startForegroundService(Intent(this, BeaconMonitoringService::class.java)) } }
3. 实现Beacon监测前台服务
把Beacon监测逻辑移到前台服务中,确保进程不被系统回收:
class BeaconMonitoringService : Service() { private val TAG = "BeaconService" private lateinit var beaconManager: BeaconManager private lateinit var region: Region override fun onCreate() { super.onCreate() // 启动前台通知(Android 8.0+必需,否则服务会被系统杀死) startForeground(NOTIFICATION_ID, createForegroundNotification()) // 初始化BeaconManager beaconManager = BeaconManager.getInstanceForApplication(this) region = Region("FetchVision", null, null, null) // 优化后台扫描参数 beaconManager.backgroundScanPeriod = 10000 // 后台扫描时长10秒 beaconManager.backgroundBetweenScanPeriod = 30000 // 扫描间隔休息30秒 // 监听区域状态变化 beaconManager.getRegionViewModel(region).regionState.observeForever(monitoringObserver) beaconManager.startMonitoring(region) } private val monitoringObserver = Observer<Int> { state -> if (state == MonitorNotifier.INSIDE) { Log.d(TAG, "检测到Beacon,发送API请求") sendRequest() // 执行你的POST请求逻辑 } else { Log.d(TAG, "未检测到Beacon") } } private fun createForegroundNotification(): Notification { val channelId = "beacon_monitoring_channel" // 创建通知渠道(Android 8.0+必需) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel( channelId, "Beacon监测服务", NotificationManager.IMPORTANCE_LOW // 低优先级减少用户打扰 ) getSystemService(NotificationManager::class.java).createNotificationChannel(channel) } return NotificationCompat.Builder(this, channelId) .setContentTitle("Beacon监测中") .setContentText("后台持续监测BLE设备") .setSmallIcon(R.drawable.ic_notification) // 替换为你的通知图标 .setPriority(NotificationCompat.PRIORITY_LOW) .build() } override fun onBind(intent: Intent): IBinder? = null companion object { private const val NOTIFICATION_ID = 1001 } }
4. 引导用户忽略电池优化
部分厂商的省电策略仍可能杀死前台服务,需引导用户开启忽略电池优化:
private fun requestIgnoreBatteryOptimizations() { val intent = Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) intent.data = Uri.parse("package:$packageName") startActivity(intent) }
关键注意点
- 前台服务的通知不能隐藏(Android 12+强制要求),但可设为低优先级减少打扰
- 后台位置权限必须用户主动授权,无法自动获取
- 小米、华为等定制系统可能有额外后台限制,需引导用户开启"自启动"权限
内容的提问来源于stack exchange,提问作者NLou
相关产品推荐
相关产品推荐

