转载请标明出处:http://blog.csdn.net/xx326664162/article/details/52385720 文章出自:薛瑄的博客

你也可以查看我的其他同类文章,也会让你有一定的收货

谈起Android程序开发,就需要了解其四个主要的部件:Activity、Service、ContentProvider、 BroadcastReceiver。而其中Activity是唯一直接控制程序界面呈现,直面用户操作的部件(当然BrowadCastReceiver也能通过桌面控件(App Widgets)来呈现有限的操作界面)。Android对于Activity有严格的生命周期控制,以限制开发者在适当的回调函数里的放上合适的代码。对于多个Activity的转换,Android也有非常好的管理和流畅的切换,对此Android还引入了任务栈(Task Stack)的概念,这个概念对于Android设备上得返回按键有极其重要的联系。

(大部分文档都将其表述为Tasks and Back Stack,但从官方文档的描述来看,Android的相对于Activity讲到的Task都视为一个存放Activities的Stack,所以将其称为Task Stack也不为过。)

在AndroidManifest中申明所要用到的Activity时可以设置不同的launchMode来得到不同的Activity“启动”效果。在使用startActivity开启新的Activity时,传入的Intent也可以设置不同的Flag来达到不同的效果。另一方面,在Activity启动时它可能又开启了另一个Activity,或者调用了finish()函数终结了Activity。

这使得Activity栈变得无法掌握,有时候按下返回按钮或者点击关闭当前Activity的操作,都不知道Android系统会把程序带到那个Activity,不确定这是否是最后一个Activity以致退出了整个程序。亦或者一些按钮和操作循环产生Activity而造成内存膨胀。对于这些问题,如果能够在调试期间知道当前任务栈的情况,就能很方便的观察和发现问题存在的原因,进而选择正确的launchMode,设置恰当Intent的Flag来使程序达到预期的效果。

使用adb shell指令来查看Activity栈和Fragment栈

Android为开发者提供了adb(Android Debug Bridge),这是非常强大的调试工具。例如:logcat来显示日志记录。dumpsys。dumpsys可以添加不同的参数来指示需要输出哪一类Service的信息。
查看当前Activity :adb shell dumpsys window w | grep name=""

查看当前栈顶的Activity :adb shell dumpsys activity | grep "mFocusedActivity"

查看当前栈顶的Activity的Fragment :adb shell dumpsys activity your.package.name

本来重点来分析下面这个命令:

adb shell dumpsys activity

输入上述指令,就能得到关于设备非常长的一段讯息,但是也能清晰看出它们比较详细的分类。下面是我的一些调试信息

ACTIVITY MANAGER PENDING INTENTS (dumpsys activity intents)* PendingIntentRecord{42b05f20 com.android.vending startService}... ... ... ...ACTIVITY MANAGER BROADCAST STATE (dumpsys activity broadcasts)Historical broadcasts [foreground]:#0: BroadcastRecord{430d2fb8 u-1 android.intent.action.TIME_TICK}act=android.intent.action.TIME_TICK flg=0x50000014 (has extras)extras: Bundle[{android.intent.extra.ALARM_COUNT=1}]... ... ... ...ACTIVITY MANAGER CONTENT PROVIDERS (dumpsys activity providers)Published single-user content providers (by class):* ContentProviderRecord{429d18a8 u0 com.android.phone/.IccProvider}proc=ProcessRecord{429765d8 858:com.android.phone/1001}singleton=trueauthority=icc... ... ... ...ACTIVITY MANAGER SERVICES (dumpsys activity services)User 0 active services:* ServiceRecord{429f8668 u0 com.android.bluetooth/.hid.HidService}app=nullcreated=-1h44m27s317ms started=false connections=0... ... ... ...ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)Stack #0:Task id #28TaskRecord{43525058 #28 A=com.android.systemui U=0 sz=1}Intent { act=com.android.systemui.recent.action.TOGGLE_RECENTS flg=0x10c00000 cmp=com.android.systemui/.recent.RecentsActivity (has extras) }Hist #0: ActivityRecord{428d1ae8 u0 com.android.systemui/.recent.RecentsActivity t28}Intent { act=com.android.systemui.recent.action.TOGGLE_RECENTS flg=0x10800000 cmp=com.android.systemui/.recent.RecentsActivity bnds=[328,886][656,1176] }ProcessRecord{42968230 695:com.android.systemui/u0a12}... ... ... ...ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes)Process LRU list (sorted by oom_adj, 28 total, non-act at 3, non-svc at 3):PERS #27: sys   F/ /P  trm: 0 605:system/1000 (fixed)... ... ... ...

查看activities栈

每一个类别都有一个括号内容,给出了更加详细的指令来查看该类别下更多具体内容。因此再来尝试指令:

adb shell dumpsys activity activities

看到下边的结果:(下面的结果是经过我删减的,可先不用看懂,大概有个印象,结合后面的demo,自己运行这些命令再去观察)

C:\Users\he>adb shell dumpsys activity activities
ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Display #0 (activities from top to bottom):Stack #1:Task id #3241* TaskRecord{3a9c6b59 #3241 I=com.weixinfu.circles/.SingleTaskActivity U=0 sz=1}userId=0 effectiveUid=u0a194 mCallingUid=u0a194 mCallingPackage=com.weixinfu.circlesintent={flg=0x10000000 cmp=com.weixinfu.circles/.SingleTaskActivity}realActivity=com.weixinfu.circles/.SingleTaskActivityautoRemoveRecents=false isPersistable=true numFullscreen=1 taskType=0 mTaskToReturnTo=0rootWasReset=false mNeverRelinquishIdentity=true mReuseTask=falseActivities=[ActivityRecord{2acf5604 u0 com.weixinfu.circles/.SingleTaskActivity t3241}]askedCompatMode=false inRecents=true isAvailable=truelastThumbnail=null lastThumbnailFile=/data/system/recent_images/3241_task_thumbnail.pnghasBeenVisible=true firstActiveTime=1472625076491 lastActiveTime=1472625076491 (inactive f
or 6s)* Hist #0: ActivityRecord{2acf5604 u0 com.weixinfu.circles/.SingleTaskActivity t3241}packageName=com.weixinfu.circles processName=com.weixinfu.circleslaunchedFromUid=10194 launchedFromPackage=com.weixinfu.circles userId=0app=ProcessRecord{3d67e077 1883:com.weixinfu.circles/u0a194}...Task id #3239* TaskRecord{297f7276 #3239 A=com.weixinfu.circles U=0 sz=4}userId=0 effectiveUid=u0a194 mCallingUid=2000 mCallingPackage=nullaffinity=com.weixinfu.circlesintent={act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x100000
00 cmp=com.weixinfu.circles/.MainActivity}realActivity=com.weixinfu.circles/.MainActivityautoRemoveRecents=false isPersistable=true numFullscreen=4 taskType=0 mTaskToReturnTo=0rootWasReset=false mNeverRelinquishIdentity=true mReuseTask=falseActivities=[ActivityRecord{340043bc u0 com.weixinfu.circles/.MainActivity t3239}, Activity
Record{2396f1b0 u0 com.weixinfu.circles/.StandardActivity t3239}, ActivityRecord{1ed6243f u0 com
.weixinfu.circles/.StandardActivity t3239}, ActivityRecord{552953c u0 com.weixinfu.circles/.Sing
leTopActivity t3239}]askedCompatMode=false inRecents=true isAvailable=truelastThumbnail=android.graphics.Bitmap@3d25031e lastThumbnailFile=/data/system/recent_image
s/3239_task_thumbnail.pnghasBeenVisible=true firstActiveTime=1472625076462 lastActiveTime=1472625076462 (inactive f
or 6s)* Hist #3: ActivityRecord{552953c u0 com.weixinfu.circles/.SingleTopActivity t3239}packageName=com.weixinfu.circles processName=com.weixinfu.circleslaunchedFromUid=10194 launchedFromPackage=com.weixinfu.circles userId=0app=ProcessRecord{3d67e077 1883:com.weixinfu.circles/u0a194}...* Hist #2: ActivityRecord{1ed6243f u0 com.weixinfu.circles/.StandardActivity t3239}packageName=com.weixinfu.circles processName=com.weixinfu.circleslaunchedFromUid=10194 launchedFromPackage=com.weixinfu.circles userId=0app=ProcessRecord{3d67e077 1883:com.weixinfu.circles/u0a194}...* Hist #1: ActivityRecord{2396f1b0 u0 com.weixinfu.circles/.StandardActivity t3239}packageName=com.weixinfu.circles processName=com.weixinfu.circleslaunchedFromUid=10194 launchedFromPackage=com.weixinfu.circles userId=0app=ProcessRecord{3d67e077 1883:com.weixinfu.circles/u0a194}...* Hist #0: ActivityRecord{340043bc u0 com.weixinfu.circles/.MainActivity t3239}packageName=com.weixinfu.circles processName=com.weixinfu.circleslaunchedFromUid=2000 launchedFromPackage=null userId=0...Running activities (most recent first):TaskRecord{3a9c6b59 #3241 I=com.weixinfu.circles/.SingleTaskActivity U=0 sz=1}Run #8: ActivityRecord{2acf5604 u0 com.weixinfu.circles/.SingleTaskActivity t3241}TaskRecord{297f7276 #3239 A=com.weixinfu.circles U=0 sz=4}Run #7: ActivityRecord{552953c u0 com.weixinfu.circles/.SingleTopActivity t3239}Run #6: ActivityRecord{1ed6243f u0 com.weixinfu.circles/.StandardActivity t3239}Run #5: ActivityRecord{2396f1b0 u0 com.weixinfu.circles/.StandardActivity t3239}TaskRecord{19c8ed7b #3240 A=com.weixinfu.circles U=0 sz=1}Run #4: ActivityRecord{34684002 u0 com.weixinfu.circles/.SingleInstanceActivity t3240}TaskRecord{297f7276 #3239 A=com.weixinfu.circles U=0 sz=4}Run #3: ActivityRecord{340043bc u0 com.weixinfu.circles/.MainActivity t3239}TaskRecord{173f2d1c #3235 A=com.android.settings U=0 sz=2}Run #2: ActivityRecord{156f27de u0 com.android.settings/.SubSettings t3235}Run #1: ActivityRecord{3add385d u0 com.android.settings/.Settings t3235}TaskRecord{37bf9f30 #3220 A=com.tencent.mm U=0 sz=2}Run #0: ActivityRecord{6f06dd7 u0 com.tencent.mm/.ui.LauncherUI t3220}mResumedActivity: ActivityRecord{2acf5604 u0 com.weixinfu.circles/.SingleTaskActivity t3241}mLastPausedActivity: ActivityRecord{552953c u0 com.weixinfu.circles/.SingleTopActivity t3239
}Stack #0:Task id #3212* TaskRecord{242fa1d7 #3212 A=com.cyanogenmod.trebuchet U=0 sz=1}...* Hist #0: ActivityRecord{fd0a891 u0 com.cyanogenmod.trebuchet/com.android.launcher3.Launc
her t3212}...Running activities (most recent first):TaskRecord{242fa1d7 #3212 A=com.cyanogenmod.trebuchet U=0 sz=1}Run #0: ActivityRecord{fd0a891 u0 com.cyanogenmod.trebuchet/com.android.launcher3.Launch
er t3212}mLastPausedActivity: ActivityRecord{fd0a891 u0 com.cyanogenmod.trebuchet/com.android.launche
r3.Launcher t3212}mFocusedActivity: ActivityRecord{2acf5604 u0 com.weixinfu.circles/.SingleTaskActivity t3241}mFocusedStack=ActivityStack{1096bbf9 stackId=1, 21 tasks} mLastFocusedStack=ActivityStack{1096
bbf9 stackId=1, 21 tasks}mSleepTimeout=falsemCurTaskId=3241mUserStackInFront={}mActivityContainers={0=ActivtyContainer{0}A, 1=ActivtyContainer{1}A}

上面的结果是执行了下面的操作产生的:

打开StandardActivity
打开StandardActivity
打开SingleTopActivity
打开SingleTaskActivity
打开SingleTopActivity
打开SingleTopActivity
点击返回按钮

返回结果简要分析:

  • 整个log显示了当前所有在运行的任务栈,stack id 、Task id等

  • 每个stack中包含n个Task

  • Activity实例是存放在Task中的。

  • 一个Hist # 就是Activity的一个实例。

  • 对每个Activity也有比较详细的描述,比如activity实例的hashCode值、启动它的Intent的内容。

如果觉得内容过多,只想看看栈的内容,也可以直接跳到”Running activities (most recent first)”那部分,比较简洁而又明了的列出了栈中得Activity列表,就能知道当按下返回键的时候会应该会回到哪个Activity以后是要退出程序。

对于”Running activitie”s的内容在dumpsys activity中就有,并不需要dumpsys activity activities,也可以用下边的指令来限制仅输出”Running activities”列表:

adb shell dumpsys activity activities | sed -En -e '/Running activities/,/Run #0/p'

adb shell对于调试Android程序有很多的帮助,可惜对于adb指令都没有比较全面详细而又系统的教程。只能靠在实践中慢慢摸索,从网上零星介绍中获得。

四种启动模式

  • standard模式 也是activity的默认启动模式。

  • 不论当前 Task栈中有没有 目标activity实例,都会创建一个新的activity实例,放入当前Task栈(最近的非singleInstance模式 的Task栈)

  • singleTop模式

  • 若当前Task栈的栈顶不是 目标activity实例 ,创建一个新的activity实例,放入当前Task栈(最近的非singleInstance模式 的Task栈)

  • 若当前Task栈的栈顶是 目标activity实例,则复用该activity实例

  • singleTask模式

  • 若当前Task栈中没有 目标activity实例,则创建新的Task栈,并创建目标activity实例。(Task栈中存放activity的实例)

  • 若当前Task栈中有 目标activity实例,系统会把位于该activity上的所有activity移除Task栈,从而使得目标activity转入栈顶

  • singleTask模式的activity所在栈,可以接受其他standard模式和singleTop模式的activity实例

  • singleInstance模式

  • 若所有Task栈中都没有 activity实例,则创建新的Task栈,并创建activity实例。

  • 若存在 目标activity实例,则把activity实例所在的Task栈转到前台

  • singleInstance模式的activity所在栈,不接受standard模式、singleTop模式、singleTask模式的activity实例。

所以singleInstance模式的activity实例所在栈,永远只有一个activity实例

实现了四种启动模式的demo

原作者的下载地址,不过需要在linux下解压。或者在这里下载

通过ActivityManager获取状态

Android提供了ActivityManger来帮助开发者了解运行期间的状态,通过调用getRunningTasks(int)方法,就可以在得到RunningTaskInfo的列表,其代表着当前Android设备正在运行着的Task。从RunningTaskInfo中又可以进一步得到更多的信息

ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> runningTaskInfoList =  am.getRunningTasks(10);
for (RunningTaskInfo runningTaskInfo : runningTaskInfoList) {log("id: " + runningTaskInfo.id);log("description: " + runningTaskInfo.description);log("number of activities: " + runningTaskInfo.numActivities);log("topActivity: " + runningTaskInfo.topActivity);log("baseActivity: " + runningTaskInfo.baseActivity.toString());
}

例如文中提供的示例程序中定义了4个具有不同launchMode的Activity,每点击一次菜单栏上得选项就会弹出一个新的Activity(或者将指定Singleton的Activity置前)。

Activity上显示的数字则指示startActivity()被第几次调用时开启了这个Activity。有一些Singleton的会显示多个数字,也表明它是被复用的。

因为在onCreate()方法上放置了上述代码,所以观察log就能发现当前有多少个Task在被执行,每个Task又有多少个Activities。

缺点

必须在程序中注入调试代码,因为要控制在发布时代码必须被清理了。RunningTaskInfo虽然能够告诉我们有多少个Activity保存在其上,但是没有提供完整的列表,只能看到头尾两个Activity。给出的两个Activity的属性:topActivity和baseActivity也只是ComponentName类型,并非真实的Activity对象,因此除了类的名字没有其他更多信息。

参考:使用adb shell dumpsys检测Android的Activity任务栈

使用Adb shell dumpsys检测Android的Activity任务栈相关推荐

  1. adb shell dumpsys 使用命令和来源

    一.概述 adb shell dumpsys 在Android开发中经常要用到,平时都是零碎的积累,用到什么的时候就 记录下来,最近看了一些资料,发现可以汇总所有的命令,当带某个参数的时候,就可以查看 ...

  2. Android adb shell dumpsys activity broadcasts分析

    adb shell dumpsys activity 中的broadcasts信息 通过adb shell dumpsys activity打印中的第二项就是broadcasts信息: ACTIVIT ...

  3. Android M App休眠 (adb shell dumpsys usagestats)

    App休眠 在 Marshmallow 系统,Google 宣布了一个新的功能叫 App 休眠.App 休眠会阻止那些不 常用的 App(几天没有用过的 App)连接网络或者是运行任何程序直至设备充电 ...

  4. 打印Activity任务栈脚本:adb shell dumpsys activity

    #!/bin/bash while [ 1 ] do echo"****************************<-----开始----->*************** ...

  5. Android内存泄漏查找和解决adb shell dumpsys meminfo packagement

    1.通过adb shell dumpsys meminfo packageName来查看内存使用状况 在没有打开应用的情况下,该命令返回的数据是这样的: 2.打开这个应用的MainActivity,再 ...

  6. adb shell dumpsys activity

    1 需求 查询当前运行activity adb shell dumpsys activity | findstr mFocusedApp adb shell dumpsys activity | fi ...

  7. adb shell dumpsys简单介绍

    以下内容来自stack overflow上的一个提问,因为个人英语水平所限,就不翻译了,将主要内容整理如下,方便查阅.简而言之,介绍了如下内容 dumpsys可以用来检测系统的服务信息 列出dumps ...

  8. adb shell dumpsys package

    1 需求 获取手机中声明的所有权限 perm[issions]: dump permissions 获取手机中申请指定权限的所有应用 permission [name ...]: dump decla ...

  9. android ADB shell 命令启动 android程序

    今天用eclipase写了个android程序,主要用到了service.activity.broadcast,在安卓系统手机上调试通过,现在想用ADB shell命令启动这个程序,使达到的效果和在e ...

  10. adb shell dumpsys 命令 查看内存

    android程序内存被分为2部分:native和dalvik,dalvik就是我们平常说的java堆,我们创建的对象是在这里面分配的,而bitmap是直接在native上分配的,对于内存的限制是 n ...

最新文章

  1. 最新调查:等这一波COBOL程序员退休,很多关键岗位就后继无人了
  2. 兰州现超级“牛大”碗比腰粗:牛肉面吃出火锅范
  3. Altium designer原理图导入word文档模糊——终极解决办法
  4. [导入]LAMP架构下安装Drupal
  5. Java主线程等待子线程、线程池
  6. 怎么给没链接的flash加超链接
  7. 关于socket阻塞与非阻塞情况下的recv、seng、read、write返回值问题
  8. win7电脑插音响没声音的解决教程--win10专业版
  9. Docker网络与资源控制
  10. vue中引入百度地图
  11. Lambert漫反射模型
  12. 基于Springboot和Mybatis的文件上传与下载
  13. 计算机属性没有共享,win10系统本地连接属性里没有共享选项的具体方案
  14. 抖音小程序实践二:常用权限申请
  15. Java EE的几个常用框架简介
  16. 如何进入大数据领域,学习路线是什么?
  17. 6.1. Inserting Data
  18. CSS cursor(鼠标状态)属性
  19. 公安情报指挥一体化合成作战平台建设,指挥调度系统开发
  20. 基于GEC6818的个人超市购物系统

热门文章

  1. 一夜没睡,仍然精力充沛——工作规划-2013.07.23
  2. KNN算法说明以及sklearn 中 neighbors.KNeighborsClassifier参数说明
  3. teredo服务器文件,可用teredo服务器
  4. 计算机硕士伊利诺伊大学排名,2020年伊利诺伊大学芝加哥分校排名TFE Times美国最佳计算机科学硕士专业排名第71...
  5. threejs修改模型旋转轴
  6. 服务器bios怎么用u盘装系统,如何进入BIOS并用U盘重装系统
  7. NO.3 微信第三方平台代创建小程序审核发布以及小程序信息(头像,名称,简介)修改 以及微信错误码 返回信息
  8. udal导mysql_teledb-udal实践分享
  9. Floating point exception (core dumped)解决
  10. 编程英语(单词有音标)