1.簡介
眾所周知,Android* 開發人員頭頂許多稱呼:設計員、程式猿等,並且通常會不可避免地被稱為故障檢修工。代碼中的錯誤無法避免,因此無論您是否一開始就造成錯誤,瞭解調試工具以及如何迅速而有效地跟蹤並解決錯誤都很重要。鑒於此,如今的 Android 開發人員必須掌握有效調試技巧。本文提供了 Android 應用程式調試工具的簡單教學,用於協助 Android SDK 以及相關工具的新手迅速入門,並在 Android x86 平台上更有效地解決故障。
2.SDK 應用程式調試工具
Android SDK 提供了試應用程式所需的大多數工具。如果希望進行諸如單步調試代碼、查看變數值以及暫停執行應用程式的操作,則需要相容 JDWP 的偵錯工具。如果使用 Eclipse,則已附帶相容 JDWP 的偵錯工具,無需設定。如果使用其它 IDE,則可使用其附帶的偵錯工具並將偵錯工具與特殊連接埠串連,使其可以和您裝置上的應用程式虛擬機器通訊。
如果使用 ADT(Android 開發工具)外掛程式在 Eclipse 中進行開發,則可使用內建的 Java* 偵錯工具並結合 DDMS(Dalvik 調試監測程式伺服器)來調試應用程式。為了便於訪問偵錯工具和 DDMS,Eclipse 以視圖形式顯示偵錯工具和 DDMS 功能,這些都是自訂的 Eclipse 視圖,根據您所在的視圖顯示特定選項卡和視窗。Eclipse 還可負責為您啟動ADB (Android Debug Bridge) 主機精靈,從而無需手動運行該工具。如果使用其他 IDE 進行調試,則可使用 Android SDK 提供的所有調試工具,例如 ADB、DDMS、Java 偵錯工具等。
圖 1. Dalvik 調試監測程式伺服器
藉助 DDMS,開發人員可查看進程的堆區使用方式、跟蹤對象的記憶體配置、使用模擬器或裝置的檔案系統、檢查線程資訊、擷取方法配置、使用網路流量工具(在 Android 4.0 中提供)、使用 LogCat 跟蹤代碼資訊以及類比手機操作和位置。如欲瞭解更多資訊,請參閱 http://developer.android.com/guide/developing/debugging/ddms.html。Android SDK 還提供 Hierarchy Viewer(層級觀察器)和 layoutopt(布局最佳化分析工具)協助開發人員調試布局問題。
Hierarchy Viewer 應用程式可讓您調試並最佳化您的使用者介面 (UI)。它以可視方式呈現布局的視圖層級(View Hierarchy 口),提供放大的顯示視圖(Pixel Perfect 視窗)。
圖 2. Hierarchy Viewer(層級查看器)
View Hierarchy視窗顯示形成您裝置上或模擬器上啟動並執行活動的 UI 的視圖對象。您可以用它在整個視圖樹的上下文中查看各個視圖對象。對於每個視圖對象,View Hierarchy 視窗還顯示渲染效能資料。在選擇節點時,視圖的額外資訊出現在節點上方的小視窗中。 在單擊其中一個節點時,可看到有關映像、視圖計數和渲染時間的資訊。
圖 3. 查看對象資訊視窗
Pixel Perfect 是一個工具,用於檢查像素屬性並通過設計圖排布使用者介面。Pixel Perfect 視窗顯示模擬器或裝置上可見的螢幕的放大映像。在該視窗中,可檢查螢幕映像中各個像素的屬性。也可使用 Pixel Perfect 視窗根據位元影像設計協助排布應用程式的使用者介面。
圖 4. Pixel Perfect 視窗
layoutopt 工具可讓您分析 XML 檔案,該檔案定義應用程式的使用者介面以查詢檢視表層級中的不當之處。要運行工具,可開啟終端並從 SDK 工具/目錄啟動 layoutopt 。 變數是以空格分隔的要分析的資源的列表,可以是未編譯的資源 xml 檔案或這些檔案的目錄。工具會載入指定的 XML 檔案並根據一組預定義的規則分析它們的定義和層級。 下面是來自工具的輸出樣本:
$ layoutopt samples/ samples/compound.xml 7:23 The root-level <framelayout> can be replaced with 11:21 This LinearLayout layout or its FrameLayout parent is useless samples/simple.xml 7:7 The root-level <framelayout> can be replaced with samples/too_deep.xml -1:-1 This layout has too many nested layouts: 13 levels, it should have <= 10! 20:81 This LinearLayout layout or its LinearLayout parent is useless 24:79 This LinearLayout layout or its LinearLayout parent is useless 28:77 This LinearLayout layout or its LinearLayout parent is useless 32:75 This LinearLayout layout or its LinearLayout parent is useless 36:73 This LinearLayout layout or its LinearLayout parent is useless 40:71 This LinearLayout layout or its LinearLayout parent is useless 44:69 This LinearLayout layout or its LinearLayout parent is useless 48:67 This LinearLayout layout or its LinearLayout parent is useless 52:65 This LinearLayout layout or its LinearLayout parent is useless 56:63 This LinearLayout layout or its LinearLayout parent is useless samples/too_many.xml 7:413 The root-level <framelayout> can be replaced with -1:-1 This layout has too many views: 81 views, it should have <= 80! samples/useless.xml 7:19 The root-level <framelayout> can be replaced with 11:17 This LinearLayout layout or its FrameLayout parent is useless</framelayout></framelayout></framelayout></framelayout>
Traceview 是執行日誌的圖形化查看器,這些日誌在您使用調試類記錄代碼中的跟蹤資訊時建立。Traceview 可協助您調試應用程式並概述其效能。Traceview 可載入記錄檔並在視窗中顯示其資料,該視窗 5 和圖 6 所示以兩個面板將您的應用程式可視化:
圖 5. 時間軸面板描述每個線程和方法何時開始和停止
圖 6. Profile(概要)面板提供方法中花費的所有時間的摘要。
dmtracedump 是一種工具,為您提供一種備選方式,用於從追蹤記錄檔檔案產生圖形調用棧圖。該工具使用 Graphviz Dot 公用程式建立圖形化輸出,因此您需要在運行 dmtracedump 之前安裝 Graphviz。dmtracedump 工具以樹圖形式產生呼叫堆疊資料,每個調用表示為一個節點。它使用箭頭顯示調用流程(從父節點至子節點)。圖 7 顯示了 dmtracedump 輸出的一個樣本。
圖 7. dmtracedump
3.NDK 應用程式調試工具
由於 Android NDK 基於 GCC 工具鏈,Android NDK 包含 GDB、GNU 偵錯工具,因而可讓您啟動、暫停、檢查和修改程式。在 Android 裝置上,GDB 配置為用戶端/伺服器模式,在嵌入式裝置上這種配置更為常見。程式在裝置上作為伺服器和遠程用戶端運行。開發人員的工作站與其串連,並發送與本地應用程式相似的調試命令。GDB 本身是一個命令列公用程式,如果手動使用會顯得較為繁瑣。幸好 GDB 可由大多數 IDE 尤其是 CDT 處理。從而可直接使用 Eclipse 來添加斷點並檢查程式,但前提是先正確配置它!
通過單擊文字編輯器的左端,Eclipse 確實可方便地用 Java 和 C/C++ 源檔案插入斷點。Java 斷點藉助 ADT 外掛程式可以立即使用,該外掛程式管理通過 Android Debug Bridge 進行的調試。但對 CDT 並非如此,CDT 並不能感知 Android。因此,插入斷點將不會有作用,除非我們配置 CDT 以使用 NDK 的 GDB,GDB 本身需要綁定至原生應用程式以對其進行調試。 在 NDK 版本中改善了對偵錯工具的支援(例如,之前不能調試純原生線程)。儘管 NDK 越來越適用,但 NDK R5(甚至包括 R7)還很不完善。但是,它仍然有用處! 現在讓我們瞭解下如何調試原生應用程式。
首先通過以下步驟在我們的應用程式中啟用偵錯模式:
1)有一步操作很重要,但也很容易被忽略,那就是在 Android 項目中啟用調試標記。該操作在應用程式資訊清單 AndroidManifest.xml 中完成。請勿忘記對原生代碼使用適用的 SDK 版本:
...
2)在清單中啟用調試標記會自動以原生代碼啟用偵錯模式。但是,APP_OPTIM 標記也控制著偵錯模式。如果已在 Android.mk 中手動設定它,則檢查是否已設定其值以進行調試(並不發布)或直接刪除它:
APP_OPTIM := debug
3)現在讓我們配置將串連至裝置的 GDB 用戶端。重新編譯項目並插入裝置或啟動模擬器。運行然後離開應用程式。確保載入應用程式並且其 PID 可用。可通過使用以下命令(在 Windows 中使用 Cygwin)監聽進程來檢查它:
$ adb shell ps |grep gl2jni
應該會返回一行:
app_75 13178 1378 201108 68672 ffffffff 80118883 S com.android.gl2jni
4)開啟終端視窗並轉到項目目錄。運行 ndk-gdb 命令(位於 Android NDK 檔案夾,例如 android-ndk-r8):
$ ndk-gdb
該命令不會返回訊息,但是會在 objlocal? 目錄建立三個檔案(對於 arm 裝置目錄為 objlocalarmeabi):
- gdb.setup:這是為 GDB 用戶端產生的設定檔。
- app_process:該檔案直接從您的裝置檢索。其為系統可執行檔,在系統啟動時啟動,並可形成分支,啟動新的應用程式。GBD 需要該參考檔案來尋找其標記。在某些方面,其為您的應用程式的二進位輸入焦點。
- libc.so:該檔案也可直接從您的裝置檢索。其為 GDB 使用的 Android 標準 C 庫(通常稱為 bionic),用於保持跟蹤運行時期間建立的所有原生線程。
5)在您的項目目錄中,複製 objlocal?gdb.setup 並將其命名為 gdb2.setup。開啟它並刪除請求 GDB 用戶端串連至運行於裝置上的 GDB 伺服器的以下行(將由 Eclipse 自身執行):
target remote :5039
6)在 Eclipse 主菜單中,轉至“Run(運行)| Debug Configurations(調試配置)...”,並在名為 GL2JNIActivityDefault 的 C/C++ 應用程式項目中建立新的調試配置。該配置將在您的電腦上啟動 GDB 用戶端並串連至裝置上啟動並執行 GDB 伺服器。
7)在 Main(主菜單)選項卡中,使用瀏覽按鈕,將項目設定為自己的項目目錄,將 C/C++ 應用程式設定為指向 objlocal x86app_process(可以使用絕對或相對路徑)。
圖 8. 為 C/C++ 應用程式調試配置
8)使用視窗底部的連結“Select other(選擇其他)...”,將啟動程式類型切換為“Standard Create Process Launcher(標準建立進程啟動程式)”:
圖 9. 選擇首選啟動程式
9)轉至偵錯工具檔案並設定偵錯工具類型為 gdbserver,將 GDB 偵錯工具設定為 android-ndk-r8 oolchains?-4.4.3prebuiltwindowsini686-android-linux-gdb.exe 或針對 arm 平台設定為 android-ndk-r8 oolchainsarm-linux-androideabi-4.4.3prebuiltlinux-x86inarm-linux-androideabi-gdb,針對 arm 平台將 GDB 命令檔案需求設定為指向位於 objlocal? 或 objlocalarmeabi 中的 gdb2.setup 檔案(使用絕對或相對路徑均可)。
圖 10. 偵錯工具設定面板
10)轉至 Connection(串連)選項卡並將類型設定為 TCP。主機名稱、IP 位址和連接埠號碼 (localhost d 5039) 都保留預設值。
圖 11. 偵錯工具設定面板上的連結設定
11)現在讓我們配置 Eclipse 以在裝置上運行 GDB 伺服器。複製 android-ndk-r8 dk-gdb 並用文字編輯器開啟它。尋找以下行:
$GDBCLIENT -x `native_path $GDBSETUP`
由於 GDB 用戶端將由 Eclipse 本身運行,因此對其進行注釋:
#$GDBCLIENT -x `native_path $GDBSETUP`
12)在 Eclipse 主菜單中,轉到“Run(運行)| External Tools(外部工具)| External Tools Configurations(外部工具
配置)...”,並建立新配置 GL2JNIActivity_GDB。
該配置將在裝置上啟動 GDB 伺服器。
13)在 Main(主菜單)選項卡上,將位置設定為指向 android-ndk-r8 中我們修改過的 ndk-gdb。 將工作目錄設定為您的應用程式目錄位置
也可設定 Arguments(變數)文字框:
Verbose:詳細查看 Eclipse 控制台中發生了什麼。
Force:自動終止之前所有會話。
start:讓 GDB 伺服器啟動應用程式,而不是在應用程式啟動之後串連至應用程式。該選項在您僅調試原生代碼而非 Java 代碼時有用。
圖 12. 外部工具配置
14)現在,和往常一樣啟動應用程式。
15)一旦應用程式啟動,就可直接通過控制台啟動 ndk-gdb 或啟動外部工具配置 GL2JNIActivity_GDB,該配置將啟動裝置上的 GDB 伺服器。GDB 伺服器接收遠程 GDB 用戶端發送的調試命令,並在本地調試您的應用程式。
16)開啟 jnigl_code.cpp 並通過雙擊文字編輯器的左端在 setupGraphics 中設定斷點(或按右鍵並選擇 Toggle breakpoint(切換斷點))。
圖 13. 斷點設定
17)最後啟動 GL2JNIActivity 預設 C/C++ 應用程式配置啟動 GDB 用戶端。它會通過通訊端串連將調試命令從 Eclipse CDT 中繼至 GDB 伺服器。從開發人員的觀點來看,這與調試本地應用程式很相似。
也有一些專用工具用於調試圖形效能,例如 Intel® GPA System Analyzer 為英特爾® 圖形效能分析器(英特爾® GPA)之一,新增加了對於英特爾架構 Android 裝置的支援,並且專供應用程式和驅動程式工程師最佳化其 OpenGL* ES 工作量。
該部分提供的資訊涉及如何配置英特爾 GPA 並通過 USB 串連將其用於您的 Android 裝置。在串連至 Android 裝置時,英特爾 GPA System Analyzer 提供 OpenGL ES API、CPU 和 GPU 效能標準,並通過提供多個圖形管線狀態重寫以協助分析 OpenGL ES 應用程式效能。
要在基於 Android x86 的裝置上使用英特爾 GPA System Analyzer,需要從文檔檢查目標機器和韌體/版本。
要開始收集標準,需要在用戶端系統上安裝英特爾 GPA System Analyzer 並將其串連至目標裝置:
1)在 Windows*/Linux* 用戶端機器上安裝英特爾 GPA 2012 R3。
2)啟動英特爾 GPA System Analyzer。
3)確保 Android 裝置通過 USB 電纜連線至用戶端系統。
4)在用戶端系統檢測目標裝置時,最多等待 10 秒。發現的裝置會出現在對話方塊視窗中。目標裝置的列表會每隔 5 到 6 秒重新整理一次。
5)尋找要串連的裝置並單擊“Connect(串連)”。英特爾 GPA System Analyzer 會將所需的組件複製到目標裝置並產生已安裝應用程式的列表。可通過單擊“Stop(停止)”中斷串連進程。
圖 14. 選擇互聯裝置
6)從可用應用程式列表中選擇所需的應用程式。“Application List(應用程式列表)”螢幕顯示所有使用者以及 Android 裝置上安裝的所有系統應用程式。
圖 15. 應用列表
7)將會啟動應用程式並且您將在英特爾 GPA System Analyzer 視窗中看到其資料。
8)要切換至不同應用程式,單擊“Back(返回)”。請注意,將強制關閉正在啟動並執行應用程式。
9)要切換至不同目標,單擊“Back(返回)”。
PowerVR 顯卡架構由以下核心模組構成,這些模組可將提交的 3D 應用程式資料轉換為渲染的圖形:Tile Accelerator (TA)、Image Synthesis Processor (ISP) 以及 Texture & Shading Processor (TSP)。“GPU” 組中的英特爾 GPA 標準對應這些核心模組之一,“Metrics List(標準列表)”中標準的順序取決於圖形管線中核心模組的順序。
圖 16. Intel GPA System Analyzer 視窗
Perf 是自 Linux 版本 2.6.30 起 Linux 中很有用的一個工具,可同時用於與硬體和軟體相關的效能分析。儘管 Android 基於 Linux 構建,但和不包含其他 Linux 組件和庫一樣,它也不包含 perf。您必須將靜態構建的 perf 推送至其中。如果您已有該工具,只需將其置於 /system/bin/ 下,就可有效發揮其作用。有關 perf 的簡短說明、基本用法和教程,可訪問https://perf.wiki.kernel.org/index.php/Main_Page。
藉助 traceview,開發人員可擷取 Java 代碼的效能資訊;藉助 perf,開發人員可擷取有關原生和系統級代碼的效能資訊, 17 中所示。
圖 17. 效能統計資料
圖 18. 函數調用棧
UxTune 是一個工程工具,用於 Android 使用者互動分析和最佳化。它是一種增強 pyTimeChart 工具。
UxTune 設計特性包括: