如何模拟Android杀死我的进程

时间:2012-07-06 15:36:14

标签: android

如果进程处于后台并且操作系统决定需要资源(RAM,CPU等),Android将终止该进程。我需要能够在测试期间模拟这种行为,以便我可以确保我的应用程序正常运行。我希望能够以自动方式执行此操作,以便我可以测试应用程序在发生这种情况时是否正常运行,这意味着我必须在每个活动中对此进行测试等。

我知道如何杀死我的进程。那不是问题。问题是,当我终止我的进程时(使用DDMS,adb shell killProcess.killProcess()等),Android不会像Android操作系统自杀一样重启它。

如果Android操作系统终止进程(由于资源需求),当用户返回应用程序时,Android将重新创建该进程,然后在活动堆栈上重新创建顶级活动(调用{{ 1}})。

另一方面,如果终止了该过程, Android会认为活动堆栈顶部的活动行为不当,因此会自动重新创建该过程然后从活动堆栈中删除顶级活动并重新创建顶级活动下面的活动(调用onCreate()`)。这不是我想要的行为。我想要与Android杀死进程时相同的行为。

只是用图解说明,如果我的活动堆栈如下:

onCreate()

如果Android杀死进程并且用户返回应用程序,则Android会重新创建该进程并创建ActivityD。

如果我终止了该过程,Android会重新创建该过程并创建ActivityC。

15 个答案:

答案 0 :(得分:107)

为我测试这个的最好方法是这样做:

  • 在您的应用程序中打开ActivityD
  • 按主页按钮
  • 在应用程序的DDMS中按停止(这将终止应用程序进程)
  • 使用Home长按或打开的应用程序(取决于设备)返回应用程序
  • 应用程序将在重新创建的ActivityD中开始(ActivityA,ActivityB,ActivityC已经死亡,并且当你回到它们时将重新创建)

在某些设备上,您还可以使用应用程序返回应用程序(ActivityD) - >您的启动器图标,但在其他设备上,它将启动ActivityA。

Android文档就是这样说的:

  

通常,当用户从主屏幕重新选择该任务时,系统会在某些情况下清除任务(从根活动上方的堆栈中删除所有活动)。通常,如果用户未访问任务一段时间(例如30分钟),则会执行此操作。

答案 1 :(得分:46)

这似乎对我有用:

adb shell am kill <package_name>

这与OP提到的adb shell kill不同。

请注意am kill命令的帮助说明:

am kill: Kill all processes associated with <PACKAGE>.  Only kills.
  processes that are safe to kill -- that is, will not impact the user
  experience.

因此,如果它在前台,它就不会杀死该进程。这似乎是OP想要的,如果我离开我的应用程序,然后运行adb shell am kill <package_name>它将杀死应用程序(我已经使用设备上的ps确认了这一点)。然后,如果我回到应用程序,我回到之前的活动中 - 也就是在OP的示例中,该过程被重新创建并创建ActivityD(而不是像大多数其他杀戮方法那样的ActivityC似乎触发)。

对不起我已经为OP推迟了几年,但希望其他人会觉得这很有用。

答案 2 :(得分:17)

另一种方法,可能是一种可编写脚本的方法,因为它不需要DDMS:

一次性设置:转到“开发者选项”,选择“后台处理限制设置”,更改“标准限制”中的值。没有后台流程&#39;。

当您需要重新启动此过程时,请按主页按钮。该进程将被终止(您可以在工作室中的logcat / Android Monitor中进行验证 - 该进程将被标记为[DEAD])。然后使用任务切换器切换回应用程序。

答案 3 :(得分:13)

这个问题很老但是,这个问题有一个答案,不需要adb,Android Studio等。唯一的要求是API 23或更新。

要通过操作系统模拟应用重启,请在应用运行时运行应用设置,禁用(然后您可以启用)权限并从最近的应用返回应用。禁用权限后,操作系统会终止应用程序,但会保留已保存的实例状态。当用户返回应用程序时,将重新创建应用程序和最后一个活动(已保存状态)。

'无后台进程'方法有时会导致相同的行为,但并非总是如此。例如,如果应用程序正在运行后台服务,则“无后台进程”不执行任何操作。但该应用程序可能被系统杀死,包括其服务。即使应用程序有服务,权限方法仍然有效。

示例:

我们的应用程序有两项活动。 ActivityA是从启动器启动的主要活动。 ActivityB从ActivityA启动。我将仅显示onCreate,onStart,onStop,onDestroy方法。 Android在调用onStop之前总是调用onSaveInstanceState,因为处于停止状态的活动可以被系统杀死。 [https://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle]

许可方法:

<start app from launcher first time>
Application onCreate
ActivityA onCreate WITHOUT savedInstance
ActivityA onStart
<open ActivityB>
ActivityB onCreate WITHOUT savedInstance
ActivityB onStart
ActivityA onStop (the order is like this, it is stopped after new one is started)
<go settings>
ActivityB onStop
<disable a permission>
//Application is killed, but onDestroy methods are not called.
//Android does not call onDestroy methods if app will be killed.
<return app by recent apps>
Application onCreate (this is the important part. All static variables are reset.)
ActivityB onCreate WITH savedInstance (user does not notice activity is recreated)
//Note that ActivityA is not created yet, do not try to access it.
ActivityB onStart
<return ActivityA by back>
ActivityA onCreate WITH savedInstance (user does not notice activity is recreated)
ActivityA onStart
ActivityB onStop
ActivityB onDestroy
<press back again, return launcher>
ActivityA onStop
ActivityA onDestroy
<open app again>
//does not call Application onCreate, app was not killed
ActivityA onCreate WITHOUT savedInstance
ActivityA onStart

我想比较其他答案中提到的其他方法。

不要保留活动:这不会杀死应用程序。

<start app from launcher first time>
Application onCreate
ActivityA onCreate WITHOUT savedInstance
ActivityA onStart
<open ActivityB>
ActivityB onCreate WITHOUT savedInstance
ActivityB onStart
ActivityA onStop
ActivityA onDestroy (do not keep)
<return launcher by home button>
ActivityB onStop
ActivityB onDestroy (do not keep) 
<retun app from recent apps>
// NO Application onCreate
ActivityB onCreate WITH savedInstance (user does not notice activity recreated)
ActivityB onStart
<return ActivityA by back>
ActivityA onCreate WITH savedInstance (user does not notice activity recreated)
ActivityA onStart
ActivityB onStop
ActivityB onDestroy
<press back again, return launcher>
ActivityA onStop
ActivityA onDestroy
<open app again>
//does not call Application onCreate, app was not killed
ActivityA onCreate WITHOUT savedInstance
ActivityA onStart

强制停止方法:不存储已保存的实例状态

<start app from launcher first time>
Application onCreate
ActivityA onCreate WITHOUT savedInstance
ActivityA onStart
<open ActivityB>
ActivityB onCreate WITHOUT savedInstance
ActivityB onStart
ActivityA onStop
<go settings>
ActivityB onStop
<force stop, return app from recent apps>
Application onCreate
ActivityA onCreate WITHOUT savedInstance 
//This is important part, app is destroyed by user.
//Root activity of the task is started, not the top activity.
//Also there is no savedInstance.

答案 4 :(得分:6)

我参加派对的时间已经很晚了,在我之前的几个人给出了同样正确的答案,但是为了简化那些跟在我后面的人只需按下主页按钮并运行此命令:

adb shell ps | grep <package name> | awk '{print $2}' | xargs adb shell run-as <package name again> kill

该应用程序不会失去状态,根据我自己的经验,这与操作系统在后台杀死应用程序的方式相同。这仅适用于调试构建的应用程序

答案 5 :(得分:5)

在“设置”下的“开发者”选项中,选择“不要保留活动”,这会在您离开它们时立即销毁活动。

答案 6 :(得分:5)

这是您在Android Studio中的操作方式。

  1. 让您的设备处于调试模式,并与计算机连接。
  2. 在您的设备上打开该应用,然后转到您要测试“从死里复位”的任何活动。
  3. 按设备上的主屏幕按钮。
  4. 在Android Studio中转到Android监视器 - &gt;监视并按“终止应用程序”图标。
  5. 现在您可以通过最近的应用程序或点击它的启动器图标返回您的应用程序,我的测试中的行为也一样。

答案 7 :(得分:2)

您可以执行后续步骤来重现所寻求的行为:

  1. 打开您的应用,导航至热门活动
  2. 使用通知面板导航到任何其他全屏应用程序(例如,到系统设置 - 右上角)
  3. 终止您的申请流程
  4. 按后退按钮

答案 8 :(得分:2)

使用HOME按钮将应用程序置于后台

在Android Studio中以“ Logcat”模式选择您的进程,然后单击左下角的“终止应用程序”

现在从Android设备上的启动器启动您的应用


编辑:根据互联网,以下内容也适用:

 adb shell am kill [my-package-name]

答案 9 :(得分:1)

按Home键,然后将应用程序放在后台。然后从DDMS或ADB停止或终止该过程。

答案 10 :(得分:0)

您似乎想要测试onSaveInstanceStateonRestoreInstanceState

在真实设备上进行测试:查看SetAlwaysFinish应用。

在模拟器中进行测试:结帐立即销毁Android模拟器中Dev Tools App中的活动选项。

答案 11 :(得分:0)

问题的根源似乎是当你杀死进程时你的Activity处于前台。

您可以通过在Activity可见时(在您所描述的情况下恰好发生)按下DDMS中的停止并将其与回家后按停止并稍后返回应用程序进行比较来观察此情况。

请确保在测试中以某种方式moveTaskToBack(true)

答案 12 :(得分:0)

我不确定这是你正在寻找的答案,它更像是一种逻辑思考。

我认为你不能真正进行全自动化测试,这是模拟它的唯一方法,它将重新创建它,AKA有很多活动,Android会杀死你的应用程序。

所以我的想法或建议是制作另一个小应用程序,它不断弹出新的活动,直到Android内存不足并开始将其作为后台处理。

行中的东西:

开始活动i - &gt;如果应用程序在列表中,请检查运行过程,增加i并重新启动循环而不关闭当前活动,否则 - >&gt;减少i并关闭当前活动,返回上一步并重新检查...

答案 13 :(得分:0)

您还可以使用adb shell从终端连接到您的设备/模拟器,然后使用ps | grep <your_package_name获取流程的PID并执行kill -9 <pid>。然后从最近的应用选择器中打开最小化的应用,它将重新启动上一个活动

答案 14 :(得分:0)

当应用程序进程终止时,Android将遍历活动记录(条目代表历史记录堆栈中的活动),以及decides将哪些记录保留在历史记录中以及将哪些记录从历史记录中删除。

此处的关键点之一是名为ActivityRecord的{​​{1}}字段,Android框架工程师describe将该字段称为“我们是否获得了最后一个活动状态?”。

默认情况下,Android considers的活动处于状态。当活动任务管理器的应用程序becomes恢复到活动状态reports时,活动valid是无状态的,直到活动的应用程序notifies框架进入“已停止”状态为止。简而言之,在应用程序目标版本上,调用活动haveState和调用haveStatefalse之间的onResume()值为onStop()depending

如果我终止了该进程,Android将重新创建该进程并创建ActivityC。

在这种情况下,ActivityD在应用程序清单中没有onSaveInstanceState()属性,并且当前正在前台运行,因此Android将从历史记录中将其删除,因为系统尚未达到其最后状态。

如何模拟Android杀死我的进程

多次提到,您可以将应用程序移至后台,因此活动后堆栈中的顶部活动将保存其状态,然后您可以通过Android Debug Bridge,Android Studio终止应用程序进程或使用“开发人员选项”中的“后台进程限制”属性。之后,您的最近活动将被成功地重新创建。

尽管如此,还有另一种简单的方法可以测试应用程序进程终止情况。了解了上述所有情况以及事实,即如果您从当前运行的ActivityD启动新的ActivityE,则仅在ActivityE android:stateNotNeeded="true"方法之后才调用ActivityD onStop()回调,您可以执行以下操作。

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) {} } }

最后,有一个名为Venom的轻量级工具可以简化对应用程序进程终止的测试。