Android Studio 自带的调试程序让您能够对运行在 Android Emulator 或相连 Android 设备上的应用进行调试。有了 Android Studio 调试程序,您就可以:
要开始调试,请点击工具栏中的 Debug 。Android Studio 会构建一个 APK,用调试密钥签署它,将其安装在您选择的设备上,然后运行它并打开 Debug 窗口,如图 1 所示。如果您向项目添加 C 和 C++ 代码,Android Studio 还会在 Debug 窗口中运行 LLDB 调试程序来调试您的原生代码。
如果您点击 Debug 后 Select Deployment Target 窗口中未出现任何设备,则您需要连接设备,或点击 Create New Emulator 来建立 Android Emulator。
图 1. Debugger 窗口,显示变量的当前线程和对象树。
如果您的应用已运行在连接的设备或模拟器上,就可以按下述步骤开始调试了:
默认情况下,调试程序显示当前项目的设备和应用进程,以及计算机上所有已连接的硬件设备或虚拟设备。选择 Show all processes 可显示所有设备上的全部进程;举例来说,显示的内容包括您的应用创建的所有服务以及系统进程。
您可以从 Debugger 菜单中选择其他调试类型。默认情况下,Android Studio 使用 Auto 调试类型,根据您的项目包含 Java 还是 C/C++ 代码选择最适合您的调试程序选项。
出现 Debug 窗口。在本例中,注意 Debug 窗口标题右侧的两个标签:一个标签用于调试原生代码,另一个用于调试 Java 代码(以 -java 表示)。
独立的调试会话具有独立的标签和不同的端口号(显示在标签内的括号中)。要结束调试会话,点击该会话的标签,然后点击 Terminate 。
注:Android Studio 调试程序与垃圾回收器采用松散集成。Android 虚拟机可保证在调试程序断开连接后才会对调试程序发现的任何对象进行垃圾回收。这可能导致调试程序处于连接状态时对象累积过多。例如,如果调试程序发现某个运行中的线程,即便该线程已终止运行,系统也不会对关联的 Thread
对象进行垃圾回收。
默认情况下,Android Studio 使用 Auto 调试类型来决定使用哪个(些)调试程序,因此您在调试 Java 代码与调试 C/C++ 代码之间切换时不必更改配置。不过,您可以创建或编辑调试配置来自定义某些设置(例如添加符号目录或 LLDB 命令),或使用其他调试类型。您还可以在将调试程序连接到运行中的某个 Android 进程时从 Choose Process 对话框的 Debugger 下拉列表中选择调试类型。
有下列调试类型可供您选择:
注:Android Studio 提供了一项实验性 Java 识别 C++ 调试程序功能,让您能够利用单个 LLDB 进程同时调试 Java 和 C/C++ 断点。尽管该功能仍处于开发阶段,但您可以在 Android Studio 2.2 及以上版本中自行试用。如需了解更多信息,请访问 Android 工具网站。
系统日志会在您调试应用时显示系统消息。这些消息包括运行在设备上的应用产生的信息。如果您想利用系统日志来调试应用,请确保您的代码能够在应用处于开发阶段时写入日志消息和打印针对异常的堆叠追踪。
要在代码中写入日志消息,请使用 Log
类。日志消息可帮助您了解执行流程,它会在您与应用交互时收集系统调试输出。日志消息可以告诉您应用的哪个部分出现了故障。如需了解有关日志记录的详细信息,请参阅读取和写入日志。
下例展示了如何通过添加日志消息来确定您的 Activity 启动时先前状态信息是否可用:
import android.util.Log; ... public class MyActivity extends Activity { private static final String TAG = MyActivity.class.getSimpleName(); ... @Override public void onCreate(Bundle savedInstanceState) { if (savedInstanceState != null) { Log.d(TAG, "onCreate() Restoring previous state"); /* restore state */ } else { Log.d(TAG, "onCreate() No saved state available"); /* initialize app */ } } }
开发期间,您的代码还可以捕获异常并将堆叠追踪写入系统日志:
void someOtherMethod() { try { ... } catch (SomeException e) { Log.d(TAG, "someOtherMethod()", e); } }
注:当您已准备好发布应用时,需要从代码中移除调试日志消息和堆叠追踪打印调用。您可以通过设置一个 DEBUG
标志并将调试日志消息放入条件语句来实现移除。
Android DDMS (Dalvik Debug Monitor Server) 和 Android Monitor 窗口均显示系统以及任何特定应用进程产生的日志。要在 Android DDMS 工具窗口中查看系统日志,请执行以下操作:
您可以通过 Android DDMS 工具窗口访问 Android Studio 中提供的一些 DDMS 功能。如需了解有关 DDMS 的详细信息,请参阅使用 DDMS。
系统日志显示的消息来自 Android 服务以及其他 Android 应用。要过滤日志消息,只查看您感兴趣的内容,请使用 Android DDMS 窗口中的工具:
Android Studio 支持使用若干类型的断点来触发不同的调试操作。最常见的类型是在指定代码行暂停应用执行的行断点。暂停时,您可以检查变量,对表达式求值,然后继续逐行执行,以确定运行时错误的原因。
要添加行断点,请按如下所述操作:
当您的代码执行到达该断点时,Android Studio 会暂停应用的执行。您可以随后使用 Debugger 标签中的工具来确定应用的状态:
要检查变量的对象树,请在 Variables 视图中将其展开。如果 Variables 视图不可见,点击 Restore Variables View 。
要在当前执行点对某个表达式求值,点击 Evaluate Expression 。
要前进到下一行代码(而不进入方法),点击 Step Over 。
要前进到方法调用内的第一行,点击 Step Into 。
要前进到当前方法之外的下一行,点击 Step Out 。
要让应用继续正常运行,点击 Resume Program 。
如果您的项目使用了任何原生代码,默认情况下,Auto 调试类型会将 Java 调试程序和 LLDB 两者都作为独立进程连接到您的应用,这样一来,您无需重新启动应用或更改设置,便可在检查 Java 断点与 C/C++ 断点之间进行切换。
注:要想让 Android Studio 检测到 C 或 C++ 代码中的断点,您需要使用支持 LLDB 的调试类型,例如 Auto、Native 或 Hybrid。您可以通过编辑调试配置来更改 Android Studio 使用的调试类型。如需了解有关不同调试类型的更多信息,请阅读有关使用其他调试类型的部分。
Android Studio 将您的应用部署到目标设备时,Debug 窗口打开时会为每个调试程序进程显示一个标签或调试会话视图,如图 4 所示。
注:检查原生代码中的断点时,Android 系统会暂停运行应用的 Java 字节码的虚拟机。这意味着,在检查原生代码中的断点时,您无法与 Java 调试程序进行交互,或从 Java 调试程序会话检索任何状态信息。
提示:如果您想让 LLDB 在您每次开始调试应用时(在调试程序刚刚连接到您的应用进程之前或之后)执行某些命令,您可以将这些命令添加到您的调试配置中。
调试 C/C++ 代码时,您还可以设置称作监视点的特殊类型断点,这类断点可以在您的应用与特定内存块进行交互时暂停应用进程。如需了解更多信息,请阅读有关如何添加监视点的部分。
要查看所有断点和配置断点设置,请点击 Debug 窗口左侧的 View Breakpoints 。出现 Breakpoints 窗口,如图 5 所示。
您可以通过 Breakpoints 窗口左侧的列表启用或停用每个断点。如果停用了某个断点,Android Studio 不会在应用遇到该断点时将其暂停。从列表中选择断点可配置其设置。您可以将断点配置为初始处于停用状态,让系统在遇到其他断点时将其启用。您还可以配置在遇到断点后是否应将其停用。要为任何异常设置断点,请在断点列表中选择 Exception Breakpoints。
在 Debugger 窗口中,Frames 窗格让您能够检查导致遇到当前断点的堆叠框架。这样,您就可以浏览和检查堆叠框架,同时还可以检查 Android 应用中的线程列表。要选择线程,请使用线程选择器下拉列表并查看其堆叠框架。点击框架中的元素会在编辑器中打开源代码。您还可以按窗口框架指南中所述自定义线程呈现和导出堆叠框架。
在 Debugger 窗口中,Variables 窗格让您能够在系统将应用停止在某个断点处,并且您从 Frames 窗格选择某个框架时对变量进行检查。此外,Variables 窗格还能让您利用所选框架内提供的静态方法和/或变量对临时表达式求值。
Watches 窗格提供的功能类似,不同的是添加到 Watches 窗格的表达式可跨调试会话存留。您应该为自己经常访问或者提供的状态对当前调试会话有帮助的变量和字段添加监视。将出现如图 5 所示的 Variables 和 Watches 窗格。
要向 Watches 列表添加变量或表达式,请执行以下步骤:
要从 Watches 列表移除某一项,请选择该项,然后点击 Remove 。
选择某一项,然后点击 Up 或 Down ,可对 Watches 列表中的元素重新排序。
调试 C/C++ 代码时,您可以设置称作监视点的特殊类型断点,这类断点可以在您的应用与特定内存块进行交互时暂停应用进程。例如,如果您为某个内存块设置了两个指针并为其分配了一个监视点,则使用任一指针访问该内存块都会触发该监视点。
在 Android Studio 中,您可以通过选择特定变量在运行时创建监视点,但 LLDB 只会将该监视点分配给系统分配给该变量的内存块,而不会分配给变量本身。这与将变量添加到 Watches 窗格是不同的,在这种情况下,您可以观察变量的值,但当系统读取或更改其内存中的值时,您无法暂停应用进程。
注:当您的应用进程退出某个函数,并且系统从内存中释放其局部变量时,您需要重新分配为这些变量创建的所有监视点。
要设置监视点,您必须符合下列要求:
__attribute__((aligned(num_bytes)))
在原生代码中对齐变量,如下所示: // For a 64-bit ARM processor int my_counter __attribute__((aligned(8)));
如果您符合上述要求,就可以按下述步骤添加监视点:
右键点击占据您想跟踪的内存块的变量,然后选择 Add Watchpoint。出现一个用来配置监视点的对话框,如图 7 所示。
要查看所有监视点并配置监视点设置,请点击 Debug 窗口左侧的 View Breakpoints 。出现 Breakpoints 对话框,如图 8 所示。
在您添加监视点后,点击 Debug 窗口左侧的 Resume Program 可继续执行应用进程。默认情况下,如果您的应用尝试访问您设置了监视点的内存块,Android 系统会暂停您的应用进程,您的应用最后执行的那行代码旁会出现一个监视点图标 (),如图 9 所示。
Android Studio 允许您跟踪分配到 Java 堆上的对象,以及查看分配这些对象的类和线程。这样一来,您就可以查看在所关注时期分配的对象列表。这些信息对评估可能影响应用性能的内存使用极具价值。
Android Monitor 显示有关应用内存、CPU、GPU 和网络使用情况的信息。请参阅 Android Monitor 基础知识中有关如何使用 Android Monitor 的信息。另请参阅 Android Monitor 概览中对 Android Monitor 功能的介绍,其中包括日志记录目录 (logcat)、性能监视器、数据分析工具以及屏幕和视频拍照工具。
在调试模式下,您可以查看资源值和选择其他显示格式。在显示了 Variables 标签并选择了框架的情况下,执行以下操作:
可供选择的格式取决于所选资源的数据类型。您看到的可能是一个或多个下列选项:
MeasureSpec
。Integer
类型的数值。您可以按以下步骤创建自定义格式(数据类型渲染器):
即使您的应用未产生运行时错误,也并不意味着它不存在问题。您还应考虑下列问题:
Android 设备监视器是一个具有图形界面的独立工具,适用于若干 Android 应用调试和分析工具,包括 Dalvik Debug Monitor Server (DDMS)。您可以利用 Android 设备监视器分析内存使用情况,对方法进行性能分析,监视网络流量以及模拟来电和传入消息。
要在 Android Studio 中打开 Android 设备监视器,请点击工具栏上的 Monitor 。Android 设备监视器在新窗口中打开。
如需了解有关 Android 设备监视器和 DDMS 的详细信息,请参阅设备监视器和使用 DDMS。
Android Studio 让您能够在应用运行时捕获设备屏幕的截图或简短视频。屏幕截图和视频是有用的应用宣传材料,并且您还可以将它们附加在发送给开发团队的错误报告上。
要捕获应用的屏幕截图,请执行以下操作:
要为应用录制视频,请执行以下操作: