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

接收Intent时如何启动服务?Sleep as Android穿戴插件后台数据发送问题

解决方案:Sleep as Android可穿戴插件后台持续发数据适配方案

针对你开发Sleep as Android可穿戴插件时,遇到的后台每2分钟发送数据Intent被系统限制的问题,结合Android后台管控规则,给出以下可行方案:

1. 使用WorkManager实现定时任务(官方推荐)

WorkManager是Android官方适配全版本的后台任务调度组件,能绕过后台启动限制,确保任务稳定执行:

  • 定义数据发送任务Worker类:
class SleepDataWorker(context: Context, params: WorkerParameters) : Worker(context, params) {
    override fun doWork(): Result {
        // 组装并发送数据Intent
        val dataIntent = Intent("com.urbandroid.sleep.watch.DATA")
        dataIntent.putExtra("sensor_data", "你的采集数据内容")
        applicationContext.sendBroadcast(dataIntent)
        
        // 调度下一次2分钟后的任务
        val constraints = Constraints.Builder()
            .setRequiresBatteryNotLow(true) // 可选,按需设置执行约束
            .build()
        val periodicRequest = PeriodicWorkRequestBuilder<SleepDataWorker>(2, TimeUnit.MINUTES)
            .setConstraints(constraints)
            .build()
        WorkManager.getInstance(applicationContext).enqueue(periodicRequest)
        
        return Result.success()
    }
}
  • 在启动广播接收器中触发首次任务:
class StartTrackingReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        if ("com.urbandroid.sleep.watch.START_TRACKING" == intent.action) {
            // 立即执行一次,之后自动每2分钟重复
            val initialRequest = OneTimeWorkRequestBuilder<SleepDataWorker>().build()
            WorkManager.getInstance(context).enqueue(initialRequest)
        }
    }
}

2. 前台服务+定时任务(适配严格时间间隔需求)

如果WorkManager的调度延迟无法满足2分钟精准执行的要求,可使用前台服务配合定时逻辑:

  • 创建前台服务类:
class SleepTrackingService : Service() {
    private lateinit var handler: Handler
    private lateinit var dataRunnable: Runnable

    override fun onCreate() {
        super.onCreate()
        // 启动前台通知,避免被系统回收
        val notificationChannel = NotificationChannel(
            "SLEEP_TRACKING_CHANNEL",
            "睡眠数据采集",
            NotificationManager.IMPORTANCE_LOW
        )
        getSystemService(NotificationManager::class.java).createNotificationChannel(notificationChannel)
        
        val notification = NotificationCompat.Builder(this, "SLEEP_TRACKING_CHANNEL")
            .setContentTitle("睡眠数据采集")
            .setContentText("正在同步睡眠数据")
            .setSmallIcon(R.drawable.ic_notification)
            .build()
        startForeground(1001, notification)

        // 初始化定时任务
        handler = Handler(Looper.getMainLooper())
        dataRunnable = object : Runnable {
            override fun run() {
                // 发送数据Intent
                val dataIntent = Intent("com.urbandroid.sleep.watch.DATA")
                dataIntent.putExtra("sensor_data", "你的采集数据内容")
                sendBroadcast(dataIntent)
                // 2分钟后重复执行
                handler.postDelayed(this, 2 * 60 * 1000)
            }
        }
        handler.post(dataRunnable)
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        return START_STICKY
    }

    override fun onDestroy() {
        super.onDestroy()
        handler.removeCallbacks(dataRunnable)
    }

    override fun onBind(intent: Intent): IBinder? {
        return null
    }
}
  • 在启动广播接收器中启动前台服务:
class StartTrackingReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        if ("com.urbandroid.sleep.watch.START_TRACKING" == intent.action) {
            val serviceIntent = Intent(context, SleepTrackingService::class.java)
            ContextCompat.startForegroundService(context, serviceIntent)
        }
    }
}

关键适配注意事项

  • 禁止在BroadcastReceiver中直接执行耗时操作或启动后台服务,其生命周期极短,极易被系统回收。
  • Android 12及以上版本,前台服务需动态申请POST_NOTIFICATIONS权限,否则无法正常显示前台通知。
  • 若尝试使用AlarmManager,需注意setExactAndAllowWhileIdle()等方法有15分钟的调用频率限制,不适合2分钟间隔的场景,因此不推荐。

内容的提问来源于stack exchange,提问作者KTibow

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 00:38:21