本文已参与「新人创作礼」活动,一起开启掘金创作之路。Android Studio断点

1,207 阅读8分钟

概述 : Android studio 断点调试技巧分享

1 断点简介

1.1断点种类

  1. 普通断点
  2. 方法断点
  3. 字段断点
  4. 条件断点
  5. 异常断点

1.2断点执行方法

  • step over F6(单步跳过)

  • Step Into F5:单步执行,遇到子函数就进入并且继续单步执行(简而言之,进入子函数)。

  • Force step into:强制进入,在调试的时候能进入任何方法。

  • Drop Frame:回退到被调用方法处. 当需要知道当前断点的上一层调用源时,可以使用这个步骤;或是希望重新执行前面的程序,可以回退到前面的方法。

  • step out F7: 当单步执行到子函数内时,用step out就可以执行完子函数余下部分,并返回到上一层函数.与Drop Frame相似,但有区别。 (1)Step Out回退到上一层调用方法
    (2)回退之后,原先的变量值不能回退,变量值是执行完调用方法后的值。
    (3)回退之后,再按F5也不会进入到getString()方法,因为已经执行完了。
    (4)F7等价于F5+F6 (5)Drop Frame执行后,再按F6还会继续执行,而step out会直接跳到下一步。

  • Run to Cursor:跳转到光标所在位置

1.3断点辅助信息

1.3.1断点日志

在断点执行后,在控制台输出日志。备注:不是在logcat窗口,是在Debug的Console窗口。

1.3.2断点堆栈信息

在断点执行后,在控制台输出日志,日志内容是执行断点所在代码的堆栈信息。备注:堆栈信息中不包含时间,需要看执行时间可以断点日志中增加.

示例:

Breakpoint reached
	  at com.example.test2.TActivity.onResume(TActivity.java:75)
	  at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1472)
	  at android.app.Activity.performResume(Activity.java:8351)
	  at android.app.ActivityThread.performResumeActivity(ActivityThread.java:5068)
	  at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:5121)
	  at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:52)
	  at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:190)
	  at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:105)
	  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2613)
	  at android.os.Handler.dispatchMessage(Handler.java:110)
	  at android.os.Looper.loop(Looper.java:219)
	  at android.app.ActivityThread.main(ActivityThread.java:8668)
	  at java.lang.reflect.Method.invoke(Method.java:-1)
	  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
	  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1109)

1.3.3断点执行信息

在断点执行后,在控制台输出该断点的简单描述日志。
示例:

 Breakpoint reached at com.example.test2.TActivity.onResume(TActivity.java:75)

2 Android Studio Debug调试功能

2.1 Android Studio菜单栏Debug功能

image.png

上图所示:

  1. debug模式重新安装运行。 应用场景:一般需要在程序启动时就需要进入debug,例如在MyApplication, main函数等。
  2. 进入Debug模式。点击之后会弹窗,然后选择进程。示例如下: 备注:非特殊情况,一般使用这种方法进入debug。因为debug过程中,程序运行较慢,影响调试速度,在打开程序进入特定界面后,再执行此操作进入Deubg模式。另外,建议开发者对该功能添加快捷键,非常实用,可以快速进入debug模式。 快捷键对应功能名称: Main menu | Run | Attach Debugger to Android Process

image.png
3. 结束debug模式。 备注:多数情况下会结束进程

2.2 Android StudioDebug菜单图解

image.png

  • 1:studio 底部debug菜单功能按钮
  • 2:StepOver
  • 3: Step Into
  • 4: Force Step Into
  • 5: Step Out
  • 6: Drop Frame
  • 7: Run to Cursor
  • 8: Evalute Expression 调试窗口
  • 9:debug Console窗口(debug日志在这里显示)
  • 10:Add To Watcehes
  • 11:恢复Debug调试
  • 12:结束Deubg调试
  • 13:断点管理窗口
  • 14:过滤所有断点
  • 15:获取内存Deump

2.3 Breakpoints 菜单

进入方法:选择断点,点击点键》More image.png

  • 1:普通断点区域
  • 2:方法断点区域
  • 3:异常断点区域
  • 4:异常断点区域
  • 5:添加断点
  • 6:删除断点
  • 7:断点开关。可关闭和打开断点,默认是打开
  • 8:断点暂停属性开关。默认勾选,非勾选状态下,程序执行到断点不会停留。
  • 9:Condition窗口。添加断点执行条件。
  • 10:执行到断点时打印堆栈信息
  • 11:执行到断点时打印断点信息
  • 12:打印自定义日志,日志都在Deubg控制台窗口显示
  • 13:设置当前断点在某断点执行之后才会执行

备注:方法断点,默认是进入和退出都会执行,这样日志会打印两次。

3 Android Studio Debug功能详解

3.1 Evalute Expression 调试窗口

打开后可在Evalute窗口输入要执行的代码,可以得到对应的结果,单行代码可省略return 示例:

image.png

快捷键对应的功能名称: Main menu | Run | Debugging Actions | Evaluate Expression...
在AS中位置如下图

image.png

使用场景: 在debug过程中,需要得到某些函数的值,且不是一直需要,可以此功能;另外,如果已经知道某些程序执行会发生异常,可以在该窗口中执行,得到的结果是一个Exception,通过查找这个异常的堆栈信息来找到造成异常的原因,同时还保证了debug不会中断,这样就不用重新写try catch问题代码。

3.2 Add To Watches

添加执行代码块。在某断点处添加了该功能,那么每次执行到该断点时都会的执行。

使用方法:选中要执行的代码段,右键》点击Add To Watches; 或者在Variables窗口点击加号,再手动输入要执行的代码。
image.png

image.png

使用场景:在调试过程需要知道某个函数的执行结果或是要执行某个方法,或者需要修改某个字段的值。
实践一:进入H5Activity,需要修改url,在onCreate方法中,获取url后,添加断点,然后使用Add To Watches功能,添加代码段 url = "new url...."。这样就可以在不修改后台数据、不重启、不修改代码的前提下快速调试
实践二:在某断点处需要长期知道某些方法的值。

3.2 Set Value

设置值。修改某断点执行时,在Variables窗口中某字段的值。 备注:只有一次有效,断点再次执行时,不会生效。 使用方法:在Variables窗口中选中要修改的字段,点击右键,点击Set Value,即可修改该字段的值。
image.png

3.3 Resume Program 和 Pause Program

恢复debug程序和暂停debug程序 使用场景:当想暂停debug时,可使用Pause Program,它与 Mute BreakPoints 的区别是前者暂停Deubg程序,后者只是关闭断点,但还在debug程序中。\

使用方法:

image.png

3.4 Mute Breakpionts

关闭所有断点

image.png

3.5 增加断点

方法一:常见增加断点的方式是在代码左侧单击左键,添加后效果如下图。 image.png

方法二:在Breakpionts窗口手动添加断点。可以添加方法断点、字段断点和异常断点。 image.png

3.6 暂停断点

默认情况下程序执行到断点会暂停,但也可以将暂停取消。这样程序照样执行,同时断点日志、堆栈信息可以正常打印。这样可以通过日志去了解程序执行情况。

3.7 断点状态

3.7.1 无效断点

ine 5250 in Secure.getString() (android.provider.Settings)  No executable code found at line 5,250 in class android.provider.Settings$Secure  Suspend: thread

翻译:在类android.provider的第5250行没有发现可执行代码。设置$安全暂停:线程

image.png

3.7.2 断点关闭

关闭断点

image.png image.png

3.7.2 断点暂停关闭

正常断点会在程序执行到断点时会暂停,等待开发者操作,把暂停属性关闭,则程序执行到断点时不会暂停。

image.png

image.png

3.8 在系统源码中打断点

方法一:通过手动添加方法断点,将系统方法添加断点。这样只能添加方法断点,且影响调试过程中运行速度。
方法二:使用Android Studio自带的模拟器,模拟器的API与APP工程中compileSdkVersion 版本要一致。因为很多手机厂商定制系统或是因为手机系统版本与工程中compileSdkVersion 版本不一致,导致无法在源码中打断点。提示断点无效。

image.png

示例在使用系统方法获取Android ID和TextView.setTextSize()方法中打断点。

image.png

image.png

4 实践

4.1 在系统方法中打断点。统计APP运行过程中获取Android Id的调用源和次数

应用场景:根据隐私协议要求,获取用户敏感信息需要申报。APP内有较多SDK和业务代码获取用户敏感信息。第三方(如梆梆、爱加密)采集这些信息是通过将APP安装在有root权限系统的手机上,通过hook对应的系统方法,打印日志来统计,而这个对一般开发者有一定门槛。

实现方法一:通过手动添加方法断点,将对应的系统方法添加断点,然后增加断点日志,打印执行时间和对应的TAG,同时打印断点信息和堆栈信息,另外要将该断点的暂停开关关闭,不需要暂时,让其正常运行。

获取Android ID API

String ANDROID_ID = Secure.getString(context.getContentResolver(), Secure.ANDROID_ID);

image.png

4.2 APP运行过程中动态添加代码执行块

应用场景:在调试过程中,需要增加一些代码,重新编译运行代价较大。可以打断点,然后在断点的Condition窗口增加执行代码块和执行条件。相当于条件断点中,增加了代码执行块。Add To Weacth只能增加一行代码,并不能增加更多代码。 示例:在某断点处添加代码块并执行

image.png