Android会杀死一个进程,如果它在后台,而操作系统决定它需要资源(RAM, CPU等)。我需要能够在测试期间模拟这种行为,以便确保我的应用程序行为正确。我希望能够以自动的方式执行此操作,以便无论何时发生此操作,我都可以测试应用程序的行为是否正确,这意味着我必须在每个活动中测试它,等等。
我知道如何终止我的进程。这不是问题所在。问题是当我杀死我的进程(使用DDMS, adb shell kill, process . killprocess()等)时,Android不会像Android操作系统杀死它一样重新启动它。
如果Android OS杀死了进程(由于资源需求),当用户返回到应用程序时,Android将重新创建进程,然后重新创建活动堆栈上的顶部活动(调用onCreate())。
另一方面,如果我杀死进程,Android假设活动堆栈顶部的活动表现不佳,因此它自动重新创建进程,然后从活动堆栈中删除顶部活动,并重新创建顶部活动下面的活动(调用onCreate() ')。这不是我想要的行为。我想要与Android终止进程时相同的行为。
简单地解释一下,如果我的activity栈是这样的:
ActivityA -> ActivityB -> ActivityC -> ActivityD
如果Android终止了该进程,用户返回到应用程序,Android将重新创建该进程并创建ActivityD。
如果我杀死了进程,Android会重新创建进程并创建ActivityC。
当应用程序进程终止时,Android会遍历活动记录(这些记录代表历史堆栈中的活动),并决定哪些活动保留在历史记录中,哪些活动从历史记录中删除。
这里的关键点之一是名为haveState的ActivityRecord字段,Android框架工程师将其描述为“我们是否获得了最后的活动状态?”
默认情况下,Android认为活动有一个状态。当应用程序向活动任务管理器服务报告活动已恢复时,活动变为无状态,并且在应用程序通知框架活动已进入停止状态之前,此状态一直有效。简单地说,根据应用程序的目标版本,onResume()被调用和onStop()或onSaveInstanceState()被调用之间的haveState值为false。
如果我杀死了进程,Android会重新创建进程并创建ActivityC。
在这种情况下,ActivityD在应用程序清单中没有android:stateNotNeeded="true"属性,它目前正在前台运行,所以android从历史记录中删除它,因为系统还没有得到它的最后一个状态。
如何模拟Android杀死我的进程
正如前面多次提到的,你可以简单地将应用程序移到后台,这样activity back堆栈中的顶部活动就会保存它的状态,之后你可以通过Android Debug Bridge, Android Studio或使用Developer Options中的后台进程限制属性来终止应用程序进程。之后,您最近的活动将成功重新创建。
尽管如此,还有另一种简单的方法来测试应用程序进程死亡场景。知道了上面描述的所有内容和事实,如果你从当前运行的ActivityD开始新的ActivityE,那么ActivityD onStop()回调只在ActivityE onResume()方法之后被调用,你可以做下面的技巧。
class TerminatorActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val isPrePie = applicationInfo.targetSdkVersion < Build.VERSION_CODES.P
val callbacks = TerminatorLifecycleCallbacks(isPrePie)
(applicationContext as Application).registerActivityLifecycleCallbacks(callbacks)
}
private class TerminatorLifecycleCallbacks(
// Before P onSaveInstanceState() was called before onStop(), starting with P it's
// called after
// Used to schedule the death as app reports server that activity has stopped
// after the latest of these was invoked
private val isPrePie: Boolean
) : ActivityLifecycleCallbacksDefault {
private val handler = Handler(Looper.getMainLooper())
override fun onActivityPostStopped(activity: Activity) {
if (isPrePie) {
terminate()
}
}
override fun onActivityPostSaveInstanceState(activity: Activity, outState: Bundle) {
if (!isPrePie) {
terminate()
}
}
fun terminate() {
handler.postDelayed(
{
Process.killProcess(Process.myPid()) // This is the end...
},
LAST_MILLIS
)
}
companion object {
// Let's wait for a while, so app can report and server can handle the update
const val LAST_MILLIS = 100L
}
}
private interface ActivityLifecycleCallbacksDefault : Application.ActivityLifecycleCallbacks {
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {}
override fun onActivityStarted(activity: Activity) {}
override fun onActivityResumed(activity: Activity) {}
override fun onActivityPaused(activity: Activity) {}
override fun onActivityStopped(activity: Activity) {}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
override fun onActivityDestroyed(activity: Activity) {}
}
}
然后,当您想要终止应用程序时,只需启动TerminatorActivity。
最后还有一个轻量级工具,它简化了应用程序进程死亡的测试,称为Venom。