談起Android程序開發(fā),就需要了解其四個(gè)主要的部件:Activity、Service、ContentProvider、 BroadcastReceiver。而其中Activity是唯一直接控制程序界面呈現(xiàn),直面用戶操作的部件(當(dāng)然BrowadCastReceiver也能通過桌面控件(App Widgets)來呈現(xiàn)有限的操作界面)。Android對(duì)于Activity有嚴(yán)格的生命周期控制,以限制開發(fā)者在適當(dāng)?shù)幕卣{(diào)函數(shù)里的放上合適的代碼。對(duì)于多個(gè)Activity的轉(zhuǎn)換,Android也有非常好的管理和流暢的切換,對(duì)此Android還引入了任務(wù)棧(Task Stack)的概念,這個(gè)概念對(duì)于Android設(shè)備上得返回按鍵有極其重要的聯(lián)系。 (大部分文檔都將其表述為Tasks and Back Stack,但從官方文檔的描述來看,Android的相對(duì)于Activity講到的Task都視為一個(gè)存放Activities的Stack,所以將其稱為Task Stack也不為過。) 在AndroidManifest中申明所要用到的Activity時(shí)可以設(shè)置不同的 這使得Activity棧變得無法掌握,有時(shí)候按下返回按鈕或者點(diǎn)擊關(guān)閉當(dāng)前Activity的操作,都不知道Android系統(tǒng)會(huì)把程序帶到那個(gè)Activity,不確定這是否是最后一個(gè)Activity以致退出了整個(gè)程序。亦或者一些按鈕和操作循環(huán)產(chǎn)生Activity而造成內(nèi)存膨脹。對(duì)于這些問題,如果能夠在調(diào)試期間知道當(dāng)前任務(wù)棧的情況,就能很方便的觀察和發(fā)現(xiàn)問題存在的原因,進(jìn)而選擇正確的
通過ActivityManager獲取狀態(tài)Android提供了ActivityManger來幫助開發(fā)者了解運(yùn)行期間的狀態(tài),通過調(diào)用
例如文中提供的示例程序中定義了4個(gè)具有不同 D/IDER ( 3700): ===================== D/IDER ( 3700): --------------------- D/IDER ( 3700): id: 25 D/IDER ( 3700): description: null D/IDER ( 3700): number of activities: 4 D/IDER ( 3700): topActivity: ComponentInfo{com.iderzheng/com.iderzheng.StandardActivity} D/IDER ( 3700): baseActivity: ComponentInfo{com.iderzheng/com.iderzheng.SingleTaskActivity} D/IDER ( 3700): --------------------- D/IDER ( 3700): id: 24 D/IDER ( 3700): description: null D/IDER ( 3700): number of activities: 1 D/IDER ( 3700): topActivity: ComponentInfo{com.iderzheng/com.iderzheng.SingleInstanceActivity} D/IDER ( 3700): baseActivity: ComponentInfo{com.iderzheng/com.iderzheng.SingleInstanceActivity} D/IDER ( 3700): --------------------- D/IDER ( 3700): id: 23 D/IDER ( 3700): description: null D/IDER ( 3700): number of activities: 2 D/IDER ( 3700): topActivity: ComponentInfo{com.iderzheng/com.iderzheng.StandardActivity} D/IDER ( 3700): baseActivity: ComponentInfo{com.iderzheng/com.iderzheng.MainActivity} D/IDER ( 3700): --------------------- D/IDER ( 3700): id: 1 D/IDER ( 3700): description: null D/IDER ( 3700): number of activities: 1 D/IDER ( 3700): topActivity: ComponentInfo{com.android.launcher/com.android.launcher2.Launcher} D/IDER ( 3700): baseActivity: ComponentInfo{com.android.launcher/com.android.launcher2.Launcher} 缺點(diǎn)必須在程序中注入調(diào)試代碼,因?yàn)橐刂圃诎l(fā)布時(shí)代碼必須被清理了。RunningTaskInfo雖然能夠告訴我們有多少個(gè)Activity保存在其上,但是沒有提供完整的列表,只能看到頭尾兩個(gè)Activity。給出的兩個(gè)Activity的屬性:topActivity和baseActivity也只是ComponentName類型,并非真實(shí)的Activity對(duì)象,因此除了類的名字沒有其他更多信息。 手動(dòng)記錄和管理Activities棧Activity的創(chuàng)建和銷毀都會(huì)有相應(yīng)的回調(diào)函數(shù): 缺點(diǎn)要讓所有Activity的 使用adb shell指令Android還為開發(fā)者提供了adb(Android Debug Bridge),這是非常強(qiáng)大的調(diào)試工具。最常用的自然是logcat來顯示日志記錄。另外一個(gè)很強(qiáng)大的指令就是這里要提到的 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=true authority=icc ... ... ... ... ACTIVITY MANAGER SERVICES (dumpsys activity services) User 0 active services: * ServiceRecord{429f8668 u0 com.android.bluetooth/.hid.HidService} app=null created=-1h44m27s317ms started=false connections=0 ... ... ... ... ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities) Stack #0: Task id #28 TaskRecord{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) ... ... ... ... 每一個(gè)類別都有一個(gè)括號(hào)內(nèi)容,給出了更加詳細(xì)的指令來查看該類別下更多具體內(nèi)容。因此再來嘗試指令: db shell dumpsys activity activities 就能看到下邊的結(jié)果 CTIVITY MANAGER ACTIVITIES (dumpsys activity activities) Stack #0: Task id #28 * TaskRecord{43525058 #28 A=com.android.systemui U=0 sz=1} ... ... ... ... * Hist #0: ActivityRecord{428d1ae8 u0 com.android.systemui/.recent.RecentsActivity t28} ... ... ... ... Task id #1 * TaskRecord{429a35f8 #1 A=com.android.launcher U=0 sz=1} ... ... ... ... * Hist #0: ActivityRecord{429a1760 u0 com.android.launcher/com.android.launcher2.Launcher t1} ... ... ... ... Running activities (most recent first): TaskRecord{43525058 #28 A=com.android.systemui U=0 sz=1} Run #1: ActivityRecord{428d1ae8 u0 com.android.systemui/.recent.RecentsActivity t28} TaskRecord{429a35f8 #1 A=com.android.launcher U=0 sz=1} Run #0: ActivityRecord{429a1760 u0 com.android.launcher/com.android.launcher2.Launcher t1} mLastPausedActivity: ActivityRecord{428d1ae8 u0 com.android.systemui/.recent.RecentsActivity t28} Stack #1: Task id #25 * TaskRecord{42b0ee20 #25 I=com.iderzheng/.SingleTaskActivity U=0 sz=5} numActivities=5 rootWasReset=false userId=0 mTaskType=0 numFullscreen=5 mOnTopOfHome=true intent={cmp=com.iderzheng/.SingleTaskActivity} realActivity=com.iderzheng/.SingleTaskActivity Activities=[ActivityRecord{42a7e160 u0 com.iderzheng/.SingleTaskActivity t25}, ActivityRecord{42bffdf0 u0 com.iderzheng/.StandardActivity t25}, ActivityRecord{42e9e8f8 u0 com.iderzheng/.SingleTopActivity t25}, ActivityRecord{434c2238 u0 com.iderzheng/.StandardActivity t25}, ActivityRecord{4279d2d8 u0 com.iderzheng/.SingleTopActivity t25}] askedCompatMode=false lastThumbnail=null lastDescription=null lastActiveTime=6229735 (inactive for 357s) * Hist #4: ActivityRecord{4279d2d8 u0 com.iderzheng/.SingleTopActivity t25} packageName=com.iderzheng processName=com.iderzheng launchedFromUid=10124 launchedFromPackage=com.iderzheng userId=0 app=ProcessRecord{4312cbb0 3700:com.iderzheng/u0a124} Intent { cmp=com.iderzheng/.SingleTopActivity bnds=[328,580][656,870] } frontOfTask=false task=TaskRecord{42b0ee20 #25 I=com.iderzheng/.SingleTaskActivity U=0 sz=5} taskAffinity=com.iderzheng realActivity=com.iderzheng/.SingleTopActivity baseDir=/data/app/com.iderzheng-1.apk dataDir=/data/data/com.iderzheng stateNotNeeded=false componentSpecified=true mActivityType=0 compat={320dpi} labelRes=0x7f0a0013 icon=0x7f020057 theme=0x7f0b0000 config={1.0 310mcc?mnc en_US ldltr sw384dp w384dp h567dp 320dpi nrml port finger -keyb/v/h -nav/h s.7} launchFailed=false launchCount=0 lastLaunchTime=-1h40m33s397ms haveState=false icicle=null state=RESUMED stopped=false delayedResume=false finishing=false keysPaused=false inHistory=true visible=true sleeping=false idle=true fullscreen=true noDisplay=false immersive=false launchMode=1 frozenBeforeDestroy=false thumbnailNeeded=false forceNewConfig=false mActivityType=APPLICATION_ACTIVITY_TYPE thumbHolder: 42b0ee20 bm=null desc=null waitingVisible=false nowVisible=true lastVisibleTime=-5m56s862ms ... ... ... ... Running activities (most recent first): TaskRecord{42b0ee20 #25 I=com.iderzheng/.SingleTaskActivity U=0 sz=5} Run #7: ActivityRecord{4279d2d8 u0 com.iderzheng/.SingleTopActivity t25} TaskRecord{429e9558 #24 A=com.iderzheng U=0 sz=1} Run #6: ActivityRecord{429d5408 u0 com.iderzheng/.SingleInstanceActivity t24} TaskRecord{42b0ee20 #25 I=com.iderzheng/.SingleTaskActivity U=0 sz=5} Run #5: ActivityRecord{434c2238 u0 com.iderzheng/.StandardActivity t25} Run #4: ActivityRecord{42e9e8f8 u0 com.iderzheng/.SingleTopActivity t25} Run #3: ActivityRecord{42bffdf0 u0 com.iderzheng/.StandardActivity t25} Run #2: ActivityRecord{42a7e160 u0 com.iderzheng/.SingleTaskActivity t25} TaskRecord{4282e508 #23 A=com.iderzheng U=0 sz=2} Run #1: ActivityRecord{429655d8 u0 com.iderzheng/.StandardActivity t23} Run #0: ActivityRecord{429564e0 u0 com.iderzheng/.MainActivity t23} ... ... ... ... Recent tasks: ... ... ... ... 整個(gè)log顯示了當(dāng)前所有在運(yùn)行的任務(wù)棧,它們的 如果覺得內(nèi)容過多,只想看看棧的內(nèi)容,也可以直接跳到”Running activities (most recent first)”那部分,比較簡潔而又明了的列出了棧中得Activity列表,就能知道當(dāng)按下返回鍵的時(shí)候會(huì)應(yīng)該會(huì)回到哪個(gè)Activity以后是要退出程序。 對(duì)于”Running activitie”s的內(nèi)容在 adb shell dumpsys activity activities | sed -En -e ‘/Running activities/,/Run #0/p‘ 缺點(diǎn)很明顯的看出,使用
|
|