是的,安卓 App 可以检测到自己处于前台、后台以及被杀掉的情况,但不同状态的检测机制和准确度有所不同。
以下是具体的实现方式和原理:
一、 检测“前台”与“后台”状态
App 切换前后台是最常见的需求,目前有非常成熟和标准的官方方案。
1. 官方推荐方案:ProcessLifecycleOwner (Jetpack Lifecycle)
这是目前最简单、最可靠的方法。它将整个 App 进程视为一个整体的生命周期组件,自动处理了 Activity 切换、屏幕旋转等复杂情况,不会产生误判。
-
原理:当 App 第一个 Activity 启动时,分发 ON_START / ON_RESUME(进入前台);当 App 最后一个 Activity 停止(且没有新的 Activity 立即启动)时,延迟约 700 毫秒后分发 ON_PAUSE / ON_STOP(进入后台)。
-
代码示例:
ProcessLifecycleOwner.get().getLifecycle().addObserver(new DefaultLifecycleObserver() { @Override public void onStart(@NonNull LifecycleOwner owner) { // App 进入前台 } @Override public void onStop(@NonNull LifecycleOwner owner) { // App 进入后台 } });
2. 传统方案:ActivityLifecycleCallbacks
如果你不想引入 Jetpack 库,可以在 Application 类中注册 Activity 生命周期回调,通过计数器来判断。
-
原理:在 onActivityStarted 中让计数器 +1,在 onActivityStopped 中让计数器 -1。如果计数器从 0 变成 1,说明进前台;如果从 1 变成 0,说明进后台。
二、 检测“被杀掉” (进程终止)
检测“被杀”比较复杂,因为我们要区分是正在被杀(临死前)还是已经被杀过了(事后追查)。
1. 临死前的感知(部分场景可用)
当 App 被杀时,系统通常不会给你留太多时间去执行代码,有时甚至是直接强制杀死(发送 SIGKILL 信号)。
-
用户在任务列表(多任务界面)滑动划掉 App:
-
如果你的 App 运行了一个 Service,你可以重写 Service 的 onTaskRemoved(Intent rootIntent) 方法。当用户在近期任务里划掉 App 时,这个方法会被回调。你可以利用这极短的时间做一些轻量级的清理或日志记录。
-
-
正常退出(极少见):
-
如果是按返回键退出最后一个 Activity,Activity.onDestroy() 会被调用。
-
-
系统内存不足被杀(Low Memory Killer) / 发生 Crash / 强制停止:
-
无法感知。系统会直接分配 SIGKILL 信号,进程瞬间死亡,onDestroy() 等任何回调都不会执行。
-
2. 死亡后的“尸检”(事后感知 - Android 11+)
在 Android 11 (API 30) 及以上版本,谷歌引入了非常强大的 ApplicationExitInfo API。App 可以在下一次启动时,查询上一次自己是为什么死掉的。
-
获取历史退出原因:
可以通过 ActivityManager.getHistoricalProcessExitReasons() 获取一个列表,里面包含了 App 最近的死亡原因。 -
支持检测的死因包括:
-
REASON_ANR:因为无响应被杀
-
REASON_CRASH:因为崩溃被杀
-
REASON_USER_REQUESTED:用户主动在任务列表划掉 / 系统设置中点击强制停止
-
REASON_LOW_MEMORY:系统内存不足被杀
-
REASON_EXCESSIVE_RESOURCE_USAGE:资源使用超标被杀
-
-
代码示例:
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { // 获取最近的退出原因 List<ApplicationExitInfo> exitReasons = am.getHistoricalProcessExitReasons(getPackageName(), 0, 1); if (!exitReasons.isEmpty()) { ApplicationExitInfo info = exitReasons.get(0); int reason = info.getReason(); // 判断到底是哪种原因 // 可以将 reason 上报到你的服务器,用于分析 App 存活率和崩溃率 } }
总结与开发建议
-
前后台状态:放心使用 ProcessLifecycleOwner,完全在你的掌控之中。
-
被杀状态:
-
千万不要依赖在 App 被杀的那一刻(比如 onDestroy)去保存重要数据,因为系统随时可能不打招呼直接干掉进程。
-
正确做法:在 App 进入后台时(即 onStop 或者 ProcessLifecycleOwner 的 onStop),就立刻持久化保存用户数据和核心状态。
-
性能监控:结合 Android 11 的 ApplicationExitInfo,在 App 每次启动时检查上次被杀的原因,有助于优化 App 性能(例如发现大量的 OOM 或 LMK 死亡,说明 App 内存占用过高)。
-
2664

被折叠的 条评论
为什么被折叠?



