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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 04:05:28