Android Studio: Mastering Debugging Tools

“Bug debugging a bug”. © Artem Chubaryan

Introduction

From then on, when anything went wrong with a computer, we said it had bugs in it. (RADM Grace Hopper)

Developers spend more time debugging existing code than writing new one (different estimates give 50–80% of total time), and studies found differences of more than 20 to 1 in the time required by different developers to debug the same problem. Experience plays important role here as well as knowledge of available debug tools. So, let’s focus on those tools.

This article might seem too obvious for experienced Android developers, but I would still recommend glancing through it. If you recently started using Android Studio — this definitely worth a read!

I will cover Android Studio 2.3.3 (latest stable release at the moment). Android Studio 3.0 is coming soon, and there are more cool features there!


Basics

  • Learn hotkeys for Step Over/Into/Out; Resume. Learning hotkeys in general is good idea :)
  • Don’t be afraid to step into source code of libraries or into decompiled classes. Reading and understanding sources helps understand how things work — and how to fix problems you have.
  • Print more logs and analyze those. Be sure, that Heisenbugs are real. Usually, if adding a breakpoint fixes the bug — then it’s threading issue. So when debugging async code — use logs.
  • Don’t practice shotgun debugging. Tell yourself: “If I don’t solve the problem using this approach within the next 30 minutes, I’ll take 10 minutes to brainstorm about different approaches and try the best one for the next hour.” (Steve McConnell)
  • If you see a NullPointerException simply adding if (foo != null) is not enough. Investigate why the the value turned null , is it really just a missing check or is there an edge case that causes the issue. Don’t fix the symptoms, fix the problem.
  • Usually, the bug is in your code, not in library you’re using. But still check out issues page on Github for that library — and save yourself few hours of debugging.

Several more, Android-specific:

  • Attach debugger to Android Process button doesn’t have a default hotkey. Assign one (I use Ctrl+Alt+Shift+Z);
  • Putting Debug.waitForDebugger() in code will make your app wait until debugger is attached (very useful for debugging something like Application.onCreate()) Check android.os.Debug class for more cool features;
  • To quickly print stack trace of the current thread you can use Thread.dumpStack()
  • Explore Developer Options on your device and try out its features. My favorites: Pointer Location, Show layout bounds, Strict Mode (flashes screen when do long operations on main thread) and Profile GPU Rendering.
  • Most of the third-party libraries have debug mode or logging that can be enabled, so check out documentation. Image libraries usually have handy overlays for debugging as well (Picasso has setIndicatorsEnabled(true) , Fresco — setDrawDebugOverlay(true).
  • Read official user guide on debugging if you haven’t done so yet.

Breakpoints

  • To add breakpoint click the left gutter along the line of code or press Ctrl+F8 (Cmd+F8). To add ‘single-hit breakpoint’ hold Alt (or Option) and click gutter. Breakpoint will be removed after being hit once. Clicking on breakpoint with Alt (Option) key held again will Enable/Disable it.
  • Right-click on breakpoint to see more cool features. You can add conditions for breakpoints, toggle off suspending, add custom logging to console, disable until another breakpoint is hit and much more. Custom logging feature is a great alternative to adding debugLog.d() statements in code and rerunning it, so be sure to try it out.

Variables

After you hit breakpoints you can use Variables and Watches to get more info about variables, fields etc. Here are some extra things you can do:

  • Mark objects using F11 (or right click -> Mark object) to easily track it down during debugging session or distinguish from another similar objects.
  • Edit values in memory withF2 (or right-click -> Set value). Nullify references, change strings on the fly, etc — it’s especially helpful to execute different branches if if or switch statements without rerunning the app.
  • Use Evaluate Expression ( Alt+F8 or Option+F8) dialog for convenience.
  • toString() is used to represent objects by default, but you can customize it. Right-click on variable -> View As -> Create… Java Data Type Renderers dialog will pop up, where you can set ‘Use following expression when rendering a node’ to configure your custom display string. Keep in mind that instead of doing this you can actually override the default toString() in your class (which is generally a good thing to do) if you own the class.

Android Monitor

Android monitor has many useful tools you should familiarize yourself with, with main tools being logcat and monitors. Here are some gotchas useful for debugging:

  • Logcat has a gear icon on the left called Configure Logcat header. There you can select format of messages, disabled some of the info.
  • On left there is a set of awesome tools: 
    Screen capture and Screen Record are handy when debugging UI issues like pixels aligning and animation lags. 
    System Info allows to obtain info about current view hierarchy, package info, memory, databases, etc. 
    Terminate Application — for cases when Android is misbehaving. 
    Layout Inspector grabs screenshot and view hierarchy dump along with all view properties and presents it nicely, so you can quickly locate view on screen. Surprisingly, many people are not aware that this tool was added few releases ago. Most useful view properties in my opinion are: id, width/height, location on screen, paddings. Makes debugging layouts many times easier.
  • Monitors section deserves a separate article, but here primarily used tool are Initiate GC, Dump Java Heap, Start Allocation Tracking and Start Method Tracing. Having some leaks, lagging UI or weird instances of objects — that’s the tools for you

Libraries and plugins:

Here are some more tools that proved to be useful (at least for me):

  • Stetho by Facebook. Debug bridge to monitor network requests, view databases, view hierarchy, etc.
  • Leakcanary by Square. Memory leaks detection.
  • Hugo by Jake Wharton. Annotation-triggered method call logging for your debug builds.
  • Frodo by Fernando Cejas. Inspired by Hugo, mainly used for logging RxJava.
  • ADB Idea plugin. Helps to Kill, Start, Restart, Uninstall App and Clear App Data with one hotkey.
  • AdbCommander plugin. A lot of useful tools, pretty much a GUI for adb: managing apps, text input, macros, shell. Very useful if you work with Android TV (typing with remote is pain).
  • adb. Don’t forget about you best friend — adb, which constantly gets new feature and becomes faster. Spend some time exploring its possibilities.

Conclusion

Debugging is hard but inevitable, know your tools and become 10 times more productive.

Corrections, suggestions and comments are welcome.

Like what you read? Give Artem Chubaryan a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.