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

Android:如何在后台每5分钟调用Application类函数并刷新通知

解决方案:结合前台活跃定时任务与锁屏解锁触发刷新

首先得明确一个核心问题:Android系统在设备休眠(锁屏且长时间无操作)时,会大幅限制后台任务的执行,普通的GlobalScope Job、CountDownTimer这类依赖主线程或无绑定协程的定时器都会被暂停甚至终止,这就是你长延迟后任务停止的根本原因。

针对你的需求(应用未被杀时,锁屏解锁后也能补更通知),可以采用**「活跃时定时刷新 + 锁屏解锁时触发补更」**的组合方案,具体实现如下:

一、后台活跃状态下的可靠定时刷新

当应用处于后台但系统未休眠(比如用户切换到其他应用但仍在操作手机),用与应用生命周期绑定的CoroutineScope替代GlobalScope,能避免协程被系统随意回收,同时防止内存泄漏:

// 在Application类中定义专属协程域,绑定应用生命周期
private val applicationScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)

fun startActiveRefresh() {
    applicationScope.launch {
        // 每5分钟执行一次,直到协程被取消
        while (isActive) {
            callRefreshAPI()
            delay(300000L) // 5分钟
        }
    }
}

// 可在应用退出时主动取消协程(结合ProcessLifecycleOwner监听前后台更稳妥)
fun stopActiveRefresh() {
    applicationScope.cancel()
}

为什么不用GlobalScope?因为它是全局协程域,不受应用生命周期管控,不仅容易引发内存泄漏,系统在后台资源紧张时也会优先回收这类无绑定的协程任务。

二、锁屏解锁时的补更逻辑

当设备锁屏进入休眠后,定时任务会停止,这时候我们通过监听SCREEN_ON广播(用户解锁屏幕时触发),检查距离上次刷新是否已超过5分钟,满足条件则立即执行刷新:

1. 在Application类中注册动态广播接收器

(不建议用Manifest静态注册,Android 8.0+对静态广播限制极多,动态注册只在应用存活时生效,正好符合你「应用被杀后无需执行」的要求)

private lateinit var screenOnReceiver: BroadcastReceiver
private var lastRefreshTime = 0L

override fun onCreate() {
    super.onCreate()
    registerScreenOnReceiver()
    startActiveRefresh() // 启动活跃状态下的定时刷新
}

private fun registerScreenOnReceiver() {
    screenOnReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            if (intent?.action == Intent.ACTION_SCREEN_ON) {
                val currentTime = System.currentTimeMillis()
                // 判断是否超过5分钟未刷新
                if (currentTime - lastRefreshTime >= 300000L) {
                    // 必须在IO协程中执行API调用,避免阻塞广播接收器的主线程
                    applicationScope.launch {
                        callRefreshAPI()
                    }
                }
            }
        }
    }
    val filter = IntentFilter(Intent.ACTION_SCREEN_ON)
    registerReceiver(screenOnReceiver, filter)
}

// 应用销毁时务必注销接收器,避免内存泄漏
override fun onTerminate() {
    super.onTerminate()
    unregisterReceiver(screenOnReceiver)
    stopActiveRefresh()
}

// 改造刷新方法,记录每次刷新的时间戳
suspend fun callRefreshAPI() {
    // 你的API调用逻辑...
    // 重新创建通知的逻辑...
    lastRefreshTime = System.currentTimeMillis()
}

2. 关键注意事项

  • 广播接收器的onReceive方法不能执行耗时操作,所以必须把API调用放到协程的IO线程中;
  • 可以结合ProcessLifecycleOwner监听应用前后台状态,在应用完全进入后台时延长刷新间隔,减少系统资源消耗;
  • 动态广播仅在应用存活时生效,完美匹配你「应用被杀后停止执行」的需求。

三、为什么之前的方案失效?

  • GlobalScope Job长延迟失效:Android系统在后台资源不足时,会优先回收无生命周期绑定的协程,长延迟任务被终止的概率极高;
  • CountDownTimer失效:它依赖主线程的消息循环,设备休眠时主线程会被暂停,定时器自然停止工作;
  • 普通Service方案:Android 8.0+之后,后台Service只能存活几分钟,除非升级为前台Service(必须显示通知),但这可能不符合你的使用场景。

这个组合方案既保证了应用活跃时的定时刷新,又能在用户解锁屏幕时补做错过的更新,完全契合你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:43:43