如何模拟Android杀死我的进程


174

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

我知道如何终止我的程序。那不是问题。问题是,当我杀死我的过程(使用DDMS, ,adb shell killProcess.killProcess()等)的Android不重新启动它以同样的方式,它将如果Android操作系统杀死了它本身。

如果Android OS终止了该进程(由于资源需求),那么当用户返回到应用程序时,Android将重新创建该进程,然后在活动堆栈上重新创建最顶部的活动(调用onCreate())。

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

仅以图形方式进行说明,如果我的活动堆栈如下所示:

    ActivityA -> ActivityB -> ActivityC -> ActivityD

如果Android终止了该进程,并且用户返回了应用程序,则Android将重新创建该进程并创建ActivityD。

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


4
您能否仅创建在后台杀死您所需的进程数量?
亚历克斯W


2
@Pang我认为您没有抓住重点。我知道如何检测到Android已终止进程。我有处理这些情况的代码。我想要做的是正确(以自动化方式)测试此代码。为了做到这一点,我需要某种方法能够激发Android杀死我的进程,就像在资源压力下通常杀死它一样。链接的问题虽然很有趣,但在这里并没有增加任何价值。
大卫·瓦瑟


@IgorGanapolsky感谢您的链接,但实际上这些链接都没有解决问题的方法。
David Wasser

Answers:


127

对我来说最好的测试方法是这样做:

  • 在您的应用程序中打开ActivityD
  • 按主页按钮
  • Terminate Application在Android Studio中的Logcat窗口中按(这会终止应用进程,请确保您在顶部的Logcat下拉列表中选择了设备和进程)
  • 长按Home或打开的应用程序返回到应用程序(取决于设备)
  • 应用程序将在重新创建的ActivityD中启动(ActivityA,ActivityB,ActivityC已死,将在您返回它们时重新创建)

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

这是Android文档对此的评价:

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


2
感谢您的回答,但这对我没有用,因为我需要一种自动化的方法来执行此操作,以进行自动化测试。
David Wasser 2013年

1
这对我真的很有帮助。
约翰·罗伯茨

6
这不是自动的,但对于我的目的来说效果很好。不跳过步骤2是非常重要的。您必须先将应用程序发送到后台,然后才能在DDMS中停止该过程才能正常工作。对于那些想知道的DOC报价来自它是在这里。尽管我不确定它们是否与主题相关,因为它<activity>与清单中的标记有关。
Tony Chan

1
正是我所需要的。谢谢。对于那些不知道的人,DDMS在Eclipse中,请转到Window-> Open Perspective,您应该在那里找到它。
理查德

4
或者,您可以转到“开发选项”并将后台限制设置为“无后台进程”,然后每次按下主页时该进程都会终止。
Joao Gavazzi

56

这似乎为我工作:

adb shell am kill <package_name>

adb shell kill与OP提到的有所不同。

请注意,该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迟到了几年,但希望其他人会发现这很有用。


谢谢!这就是我想要的!我想指定此命令的行为不同于 adb shell am force-stop。最后一个也会删除与您的应用相关的所有未决Intent(例如“通知”),而第一个不会。
bonnyz 2015年

指向研究OS源代码的任何人,以查看它杀死进程回收内存时运行的代码-我敢打赌,它与相同am kill
androidguy

在Android 7.1 Samsung J5上不起作用。ps显示了我的应用
Valgaal '19

17

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

一次设置:转到开发人员选项,选择后台进程限制设置,将值从“标准限制”更改为“无后台进程”。

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


2
有趣。我认为这不会影响前台服务,对吗?
IgorGanapolsky '17

我需要在运行2.3.3版本的Android的实际设备上执行此操作,因此这没有任何帮助。
大卫·瓦瑟

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.

〜“ 应用可能会被包含其服务的系统杀死 ”。不是前台服务...
IgorGanapolsky'9

@DavidWasser阅读规范!developer.android.com/guide/components/services.html#Foreground 前台服务是用户主动意识到的服务,而不是内存不足时系统被杀死的候选对象。
IgorGanapolsky

3
@IgorGanapolsky文档很好,尤其是如果它是完整且正确的(不幸的是不是),但是我通常更多地依靠实际的个人观察。我已经看到一个前景Service被杀死了很多次。即使系统内存不足。大多数设备制造商已为Android OS编写了自己的“优化”和“改进”,以节省电池电量。与标准的Android相比,许多设备的攻击性更强。
大卫·瓦瑟

@DavidWasser公平的观察。这些年来,您是否提出了解决方案?
IgorGanapolsky

@IgorGanapolsky不。我没有找到解决此问题的方法。这就是为什么这个问题仍然悬而未决的原因。
David Wasser

7

我参加聚会很晚,在我之前的几个人给出了相同的正确答案,但是要简化为跟在我后面的任何人,只需按主页按钮并运行以下命令:

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

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


我知道了'grep' is not recognized as an internal or external command, operable program or batch file.
Dale

但是我是在外壳中进行的run-as <package name> kill 7379,但是它使我进入了上一个活动,而不是按下主屏幕按钮时的活动。
Dale

6

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

  1. 将处于调试模式的设备连接到计算机。
  2. 打开设备上的应用,然后转到您要测试“从死里复活”的任何活动。
  3. 按设备上的主页按钮。
  4. 在Android Studio中,转到“ Android监视器->监视器”,然后按“终止应用程序”图标。
  5. 现在,您可以通过最近的应用程序返回到您的应用程序,或者单击它的启动器图标,在我的测试中行为是相同的。

2
这没有任何帮助。我需要在测试套件中以编程方式执行此操作。但是还是谢谢你。
David Wasser

另外,该答案与Mark的答案几乎相同。
David Wasser

任何想法如何通过UIAutomator或Espresso做到这一点?
IgorGanapolsky

我找不到Android Monitor - Monitors。一定是他们摆脱的东西。我开V 3.2.1
戴尔

1
@Dale Android设备监视器已在Android Studio 3.1中弃用,并已从Android Studio 3.2中删除。
瓦尔加勒

5

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

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

终止按钮

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


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

 adb shell am kill [my-package-name]

将来进行编辑:需要注意的是,Android Studio 4.0中发生了更改,如果您Run从AS 使用,Terminate则会发出Force Stop

但是,如果您随后从启动器启动,然后尝试以这种方式进行仿真,那么您将获得所需的结果(低内存行为)。


这是一个重复的答案
Onik,

@Onik其他所有对象都有一堆不必要的绒毛,例如ddms等。尽管从技术上讲是肯定的,但是stackoverflow.com/a/41975750/2413303也说了同样的话。也许我应该添加图片。
EpicPandaForce

这没有帮助。我有一个测试工具,无法从测试工具执行这些操作。而且,行为与Android终止进程时发生的行为不同。
大卫·瓦瑟

the behaviour is not the same as what happens when Android kills the process是的
EpicPandaForce

此过程向我显示了上一个活动,而不是按下主屏幕按钮时的活动。
Dale

2

您可以执行以下步骤来重现所需的行为:

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

1
感谢您的回答,但这对我没有用,因为我需要一种自动化的方法来执行此操作,以进行自动化测试。
大卫·瓦瑟

因此,这是我发现的唯一可以实际模拟Android清除内存并杀死您的应用程序的方法(我的API级别为19,因此我无法使用send-trim-memory命令)。其他命令(例如adb shell am强制停止com.my.app.package或kill)将不会重现与上述过程相同的过程!
马克·加西亚

2

在“设置”下的“开发人员”选项中,选择“不保留活动”,当您离开活动时,该活动将被销毁。

注意:根据以下有用的评论,仅当您不关心静态值被清除时才使用此选项。


这实际上与一年前已经发布并被拒绝的解决方案相同。唯一的区别似乎是用于在模拟器上进行设置的应用程序,而不是支持它的最新手机。
克里斯·斯特拉顿

1
抱歉,正如克里斯·斯特拉顿(Chris Stratton)所说,这与其他答案几乎相同。这与Android整理活动无关。这与Android杀死整个过程有关(它确实定期且有效地杀死了它,尤其是在运行Android 4.x的HTC设备上)。
大卫·瓦瑟

6
这几乎是一件好事,但它不会杀死进程,只会破坏活动。这是什么意思?您的活动将使用saveInstanceState打开,但所有静态变量仍在处理中。进程终止后,所有静态变量也被清除。
2013年

1

按“主页”按钮,然后首先将应用程序置于后台。然后从DDMS或ADB停止或终止该进程。


感谢您的回答,但这对我没有用,因为我需要一种自动化的方法来执行此操作,以进行自动化测试。
David Wasser 2014年

如果您的活动当前处于前台,Android将永远不会杀死您的进程。您正在尝试测试永远不会发生的状况。如果您的活动处于后台,则其状态已经保存,您手动杀死它与Android在内存不足的情况下杀死它之间没有区别,即该过程只是被杀死;低内存占用没有什么特别的。当内存再次可用时,您的粘性服务将重新启动(4.4除外),并且当您点击图标或近期任务时,堆栈和活动状态将恢复。
星期一

3
在您的示例中,它回到了活动C,因为您杀死了进程,而活动D在屏幕上可见(即使在内存不足的情况下也永远不会发生),并且活动C的状态已经保存在后台。仅当您的进程根本不在前台时,该进程才会被杀死,即活动D进入后台时将被保存,因此即使您的进程被杀死,活动D的状态也将被恢复。为了对每个活动进行测试,您必须先将应用发送到后台,然后再杀死它。
星期一

“〜”是什么意思,然后将应用程序首先置于后台 “”?
IgorGanapolsky

1

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


这与Android在内存不足的情况下杀死进程一样吗?我认为OP特别希望...
IgorGanapolsky

1
从理论上讲,@ IgorGanapolsky是可以的,尽管如果没有root用户,则无法在实际设备上执行此操作。
Fran Marzoa '17

0

问题的根源似乎Activity是您终止进程时处于前台。

您可以通过以下方式观察到这一点:在Activity可见的DDMS中按Stop (恰好是您所描述的内容),并将其与在回家后按Stop(停止)并稍后返回应用程序进行比较。

只要确保以moveTaskToBack(true)某种方式进行测试即可。


0

我不确定这是您要找的答案,更像是逻辑思维。

我不认为您真的可以进行全自动测试,唯一可以模拟它的方法就是重新创建它,AKA的活动太多,Android会杀死您的应用程序。

因此,我的想法或建议是制作另一个小应用程序,该应用程序会不断弹出新活动,直到Android内存不足并开始杀死它的背景为止。

一些东西:

开始活动i->检查正在运行的进程(如果该应用程序在列表中),增加i并在不关闭当前活动的情况下重新启动循环,否则->减少i并关闭当前活动,返回上一步并重新检查...


0

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

这里的关键点之一是一个ActivityRecord名为的字段haveState,Android Framework工程师将其描述为“我们是否获得了最后一个活动状态?”。

默认情况下,Android 认为该活动具有状态。该活动成为当应用程序无状态的报告,到活动任务管理器服务,活动已经恢复,这是有效的,直到应用程序通知框架,活动已进入停止状态。简而言之,取决于应用程序目标版本,haveStatefalse在活动之间onResume()调用和/ onStop()onSaveInstanceState()调用值之间。

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

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

如何模拟Android杀死我的进程

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

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

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,它可以简化对应用程序死亡的测试。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.