查看任务的活动栈

149

我正在学习平台,同时开始开发一个简单的Android应用程序。

我使用带有ADT插件0.9.6的Eclipse IDE。

我想知道是否可能查看与任务关联的Activity堆栈?

是否可以通过DDMS工具或其他任何技术实现?

基本上我需要能够查看任务的堆栈活动,以确保应用程序的行为符合预期。

我知道可以通过在Intent对象中使用标志和在<activity>元素的某些属性中控制任务行为。

然而,拥有一种工具会很不错 - 尤其是在调试模式下 - 允许开发人员直接查看Activity堆栈。


如果您正在使用Android Studio,我在这里发布了一个解决方案链接 - Nebu
10个回答

170

从命令行中,你可以使用:adb shell dumpsys activity

这会要求活动管理器打印其当前状态的转储。其中的第一部分是完整的活动历史记录,按任务组织。此外还会打印大量其他信息,因此您可能需要向上滚动一段时间才能找到所需内容。

以下是输出示例(确切内容因平台版本而异),显示最上面的任务是带有两个活动的联系人,并在其后面是带有一个活动的启动器:

当前活动管理器状态中的活动:
  * TaskRecord{44d07218 #4 A android.task.contacts}
    clearOnBackground=true numActivities=2 rootWasReset=true
    affinity=android.task.contacts
    intent={act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10600000 cmp=com.android.contacts/.DialtactsActivity bnds=[125,640][235,758]}
    origActivity=com.android.contacts/.DialtactsContactsEntryActivity
    realActivity=com.android.contacts/.DialtactsActivity
    lastActiveTime=288203177 (inactive for 14s)
    * Hist #8: HistoryRecord{44b87a30 com.android.contacts/.ViewContactActivity}
        packageName=com.android.contacts processName=android.process.acore
        launchedFromUid=10004 app=ProcessRecord{44c4f348 1168:android.process.acore/10004}
        Intent { act=android.intent.action.VIEW dat=content://com.android.contacts/contacts/lookup/144i148.144i461a29500afc8eeb/1927 cmp=com.android.contacts/.ViewContactActivity }
        frontOfTask=false task=TaskRecord{44d07218 #4 A android.task.contacts}
        taskAffinity=android.task.contacts
        realActivity=com.android.contacts/.ViewContactActivity
        base=/system/app/Contacts.apk/system/app/Contacts.apk data=/data/data/com.android.contacts
        labelRes=0x7f090012 icon=0x7f02006b theme=0x7f0e0004
        stateNotNeeded=false componentSpecified=false isHomeActivity=false
configuration={ scale=1.0 imsi=310/4 loc=en_US touch=3 keys=2/1/2 nav=2/2 orien=1 layout=34} 结果发送至=HistoryRecord{44d174d0 com.android.contacts/.DialtactsContactsEntryActivity} 结果作者=favorites 结果代码=2 启动失败=false 有状态=false 冰激凌=null 状态=恢复 停止=false 延迟恢复=false 完成=false 键暂停=false 在历史记录中=true 永久=false 启动模式=0 全屏=true 可见=true 在销毁之前冻结=false 需要缩略图=false 空闲=true 等待可见=false 现在可见=true *Hist #7: HistoryRecord{44d174d0 com.android.contacts/.DialtactsContactsEntryActivity} 包名称=com.android.contacts 进程名称=android.process.acore 启动UID=10004 应用程序=ProcessRecord{44c4f348 1168:android.process.acore/10004} 意向 { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.contacts/.DialtactsContactsEntryActivity bnds=[125,640][235,758] } 任务前台=true 任务=TaskRecord{44d07218 #4 A android.task.contacts} 任务亲和性=android.task.contacts 实际活动=com.android.contacts/.DialtactsActivity 基础=/system/app/Contacts.apk/system/app/Contacts.apk 数据=/data/data/com.android.contacts 标签Res=0x7f090007 图标=0x7f02006b 主题=0x7f0e0000 状态不需要=false 组件指定=true 是否主页活动=false 配置={ scale=1.0 imsi=310/4 loc=en_US touch=3 keys=2/1/2 nav=2/2 orien=1 layout=34} 启动失败=false 有状态=true 冰激凌=Bundle[mParcelledData.dataSize=4196] 状态=停止 停止=true 延迟恢复=false 完成=false 键暂停=false 在历史记录中=true 永久=false 启动模式=2 全屏=true 可见=false 在销毁之前冻结=false 需要缩略图=false 空闲=true *任务记录{44c4ee90 #2 A com.android.launcher} 在后台清除=true 活动数=1 根已重置=true亲和性= com.android.launcher 意图={act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10600000 cmp=com.android.launcher/.Launcher} 真实活动= com.android.launcher/.Launcher 上次活跃时间= 214734838(73483秒不活动) *历史#6:HistoryRecord{44c4d988 com.android.launcher/.Launcher} 包名= com.android.launcher 进程名称= android.process.acore launchedFromUid=0 app=ProcessRecord{44c4f348 1168:android.process.acore/10004} 意图 { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000000 cmp=com.android.launcher/.Launcher } frontOfTask=true task=TaskRecord{44c4ee90 #2 A com.android.launcher} taskAffinity= com.android.launcher 真实活动= com.android.launcher/.Launcher 基础=/system/app/Launcher.apk /system/app/Launcher.apk 数据=/data/data/com.android.launcher labelRes=0x7f0a0000 icon=0x7f020015 主题=0x103005f stateNotNeeded=true componentSpecified=false isHomeActivity=true configuration={ scale=1.0 imsi=310/4 loc=en_US touch=3 keys=2/1/2 nav=2/2 orien=1 layout=34} launchFailed=false haveState=true icicle=Bundle[mParcelledData.dataSize=5964] 状态= STOPPED stopped=true delayedResume=false finishing=false keysPaused=false inHistory=true persistent=false launchMode=2 全屏=true visible=false frozenBeforeDestroy=false thumbnailNeeded=false idle=true

1
有没有一种好的方式可以通过logcat显示当前应用程序的所有任务和活动堆栈?我们真的需要解析adb命令吗? - android developer
92
此外,如果您只想在堆栈中看到活动名称,可以执行以下操作:adb shell <enter> dumpsys activity | grep -i run - Surya Wijaya Madjid
6
好的回答!我写了一个便利脚本,它可以过滤输出以获取给定软件包的任务/活动。 - sschuberth
7
除了adb shell dmpsys activity之外,您还可以为每个列表获取例如adb shell dmpsys activity activities,以获取包含主堆栈、正在运行的活动和最近任务的“ACTIVITY MANAGER ACTIVITIES”;dumpsys activity intents用于挂起意图;dumpsys activity broadcasts用于广播状态;dumpsys activity providers用于内容提供程序;dumpsys activity services用于服务;dumpsys activity processes用于正在运行的进程。 - Fredrick Gauss
有任何想法如何以编程的方式获取ActivityRecord的详细信息吗? - AndroidGuy
2
@SuryaWijayaMadjid的命令可以在一行中完成:adb shell dumpsys activity | grep -i run,或者使用adb shell dumpsys activity activities | grep -i run以获得稍微更清晰的输出。 - vaughandroid

67
您可以在命令行中使用以下命令来查看系统中的任务和后退栈:
adb shell dumpsys activity activities | sed -En -e '/Stack #/p' -e '/Running activities/,/Run #0/p'

或者您可以尝试TaskLogger,这是我创建的一个简单工具,它可以监视您应用程序中的所有活动和任务,并实时在Logcat中输出它们。


+1....我已经尝试了你的TaskLogger,它是一个很好的工具,帮助了我很多,但是打印了大量不需要的日志。 - ThinkDeep

45
如果您想检查特定包的任务栈,可以使用以下命令:
adb shell dumpsys activity activities | grep PACKAGE_NAME | grep Hist

我发现,grep Hist 不是实时活动堆栈,但 grep Run 是。 - thecr0w

35

我知道这个问题已经很老了,但是这个功能现在已经内置于Android Studio中:

android studio screenshot

然后在生成的文本文件中搜索 ACTIVITY(全大写):

android studio text file screenshot


22
我认为自从 Android Studio 3.0 推出新的 Android Profiler 窗口取代了 Android Monitor 工具后,这个选项已经不存在了。 - 林果皞
6
我已经针对这个缺失的功能创建了一个问题:https://issuetracker.google.com/issues/77944626,请投票支持。谢谢。 - mtrakal

14

查看最近任务列表

adb shell dumpsys activity recents

列出正在运行的服务

adb shell dumpsys activity services

查看当前内容提供程序列表

adb shell dumpsys activity providers

广播状态列表

adb shell dumpsys activity broadcasts

关于待处理意图列表

adb shell dumpsys activity intents

有关权限列表,请参阅

adb shell dumpsys activity permissions

如果您更喜欢GUI方式,可以使用AdbCommander插件,并将这些命令添加到“宏”选项卡中。 - prot0n

12

我总是会检查长错误信息中的这一部分...

  Running activities (most recent first):
TaskRecord{4307f828 #56 A com.demo.proj U 0}
  Run #4: ActivityRecord{425a6838 com.demo.proj/com.demo.proj.Activity2}
  Run #3: ActivityRecord{427dc860 com.demo.proj/com.demo.proj.Activity1}
  Run #2: ActivityRecord{420cba18 com.demo.proj/com.demo.proj.MainActivity}
TaskRecord{430341d0 #2 A com.lge.launcher2 U 0}
  Run #1: ActivityRecord{41e0af68 com.lge.launcher2/.Launcher}
TaskRecord{44e26ce0 #18 A com.lge.appbox.client U 0}
  Run #0: ActivityRecord{41e9dbe8 com.lge.appbox.client/.AppBoxClient}

注意:第四次运行是您现在在屏幕上看到的活动。 :)


2
什么是“长转储消息”? - Marian Paździoch
2
@MarianPaździoch "adb shell dumpsys activity" 显示了过长的消息。上面的消息只是其中一部分。顺便说一下,我有一个提示可以避免这个问题。运行这个命令:"adb shell dumpsys activity activities",你可以看到更短的消息,并且更容易阅读关于活动堆栈的信息。 :) - cmcromance
1
如果列表仍然太长,打开最近使用的应用程序列表并滑动关闭一些任务。 - Barry Fruitman

11

1
在Android Studio Electric Eel上似乎出现了问题:java.lang.AbstractMethodError: Receiver class com.cheng.plugins.adb.ActivityStackCommand$1 does not define or inherit an implementation of the resolved method 'abstract void processNewLines(java.util.List)' of abstract class org.jetbrains.android.util.AndroidOutputReceiver. - VIN
1
我同意@VIN所说的话。在Electric Eel中无法工作。我能想到的最好方法是运行这个命令 adb shell dumpsys activity activities | grep YOUR_PACKAGE_NAME | grep Hist - Ramakrishna Joshi

10

您可以使用工具hierarchyviewer.bat。它是android SDK的一部分。但它只适用于模拟器。但是它更加舒适和清晰。

编辑:我刚刚在Eclipse中找到了层次结构查看器!它也可以与真实设备一起使用。只需打开透视图Windows->Open Perspective->Hierarchy View,在列表中您可以看到所有连接的设备和模拟器以及活动堆栈。此外,您还可以在树形视图中查看有关视图本身的更多信息。

编辑: 出于安全原因,层次结构查看器仅适用于开发设备。生产设备无法使用。有关更多信息,请查看以下答案


4
Hierarchy Viewer 用于查看一个 Activity 的视图层级结构。这个问题是关于任务/活动栈的。 - Jeremy Logan

1
解决方案:'adb shell dumpsys activity' 无法与 TabActivity 一起使用。当选择每个选项卡项目时,相应的活动将被启动。但是当使用 'adb shell dumpsys activity' 时,它总是返回 'main' 活动。
public class main extends TabActivity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        Log.e("xyz", "start main...............");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Resources res = getResources(); // Resource object to get Drawables
        TabHost tabHost = getTabHost();  // The activity TabHost
        TabHost.TabSpec spec;  // Resusable TabSpec for each tab
        Intent intent;  // Reusable Intent for each tab

        // Create an Intent to launch an Activity for the tab (to be reused)
        intent = new Intent().setClass(this, widgets.class);
        spec = tabHost.newTabSpec("Widgets").setIndicator("Widgets", res.getDrawable(R.drawable.tab1)).setContent(intent);
        tabHost.addTab(spec);

        intent = new Intent().setClass(this, layouts.class);
        spec = tabHost.newTabSpec("Layouts").setIndicator("Layouts",res.getDrawable(R.drawable.tab2)).setContent(intent);
        tabHost.addTab(spec);

        intent = new Intent().setClass(this, composite1.class);
        spec = tabHost.newTabSpec("Composite").setIndicator("Composite",res.getDrawable(R.drawable.tab3)).setContent(intent);
        tabHost.addTab(spec);

        intent = new Intent().setClass(this, imageMedia.class);
        spec = tabHost.newTabSpec("Image_Media").setIndicator("Image&Media",res.getDrawable(R.drawable.tab4)).setContent(intent);
        tabHost.addTab(spec);

        intent = new Intent().setClass(this, timeDate.class);
        spec = tabHost.newTabSpec("Time_Date").setIndicator("Time&Date",res.getDrawable(R.drawable.tab5)).setContent(intent);
        tabHost.addTab(spec);

        intent = new Intent().setClass(this, transitions.class);
        spec = tabHost.newTabSpec("Transitions").setIndicator("Transitions",res.getDrawable(R.drawable.tab6)).setContent(intent);
        tabHost.addTab(spec);

        intent = new Intent().setClass(this, advanced.class);
        spec = tabHost.newTabSpec("Advanced").setIndicator("Advanced",res.getDrawable(R.drawable.tab7)).setContent(intent);
        tabHost.addTab(spec);

        intent = new Intent().setClass(this, others.class);
        spec = tabHost.newTabSpec("Others").setIndicator("Others",res.getDrawable(R.drawable.tab8)).setContent(intent);
        tabHost.addTab(spec);

        intent = new Intent().setClass(this, Dynamic.class);
        spec = tabHost.newTabSpec("Dynamic").setIndicator("Dynamic",res.getDrawable(R.drawable.tab2)).setContent(intent);
        tabHost.addTab(spec);

        tabHost.setCurrentTab(0);

    }
}

0

根据您提到的具体要求和希望在Android Studio中快速了解当前的后退堆栈,我开发了一个有用的插件,名为“Android Activity Back Stack Viewer”。该插件解决了对活动堆栈的可视化需求,使您更容易确保应用程序的行为符合预期。

主要特点:

  1. 可视化表示:该插件在Android Studio中提供了一个用户友好的界面,让您可以快速查看当前的活动堆栈。

  2. 简单易用:它被设计为简单直观,清晰地展示您的应用程序的任务和活动关系。

反馈和贡献:

我知道软件会不断发展,用户反馈非常宝贵。如果您有功能请求、遇到错误或在使用插件时遇到任何问题,请随时通过项目的GitLab Issues页面提交。此外,我欢迎社区的贡献和改进。如果您有增强插件的想法,请随时提交合并请求。

获取插件:

你可以在Android Studio的JetBrains插件市场上找到“Android Activity Back Stack Viewer”插件。只需使用该名称进行搜索,或者您可以直接通过此链接访问:Android Activity Back Stack Viewer Plugin截图: 这是插件在当前状态下的截图: enter image description here 希望您在Android开发过程中能够发现这个插件的有用之处。非常感谢您的反馈和贡献。如果您有任何进一步的问题或建议,请随时告诉我!

你的回答目前写得不够清楚。请编辑以添加更多细节,以帮助其他人理解这如何回答所提出的问题。你可以在帮助中心找到更多关于如何撰写好的回答的信息。 - undefined
刚刚为插件添加了自动刷新功能。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接