Logcat & Basic Debugging

Android Studio: The IDE Itself

Chapter 4 · Logcat & Basic Debugging

Once a project builds and runs (Chapters 2-3), the next real skill is finding out what it's actually doing — and, when something's wrong, why. This chapter covers the two most immediate day-to-day tools for that: Logcat, the app's own running commentary, and the Debugger, which stops execution to let you inspect it directly.

Logcat: The App's Own Running Commentary

Log.d("MainActivity", "User tapped submit button"); Log.e("NetworkClient", "Request failed", exception);

Log.d/Log.e/Log.w/Log.i calls scattered through an app's own code produce output visible in Logcat, each carrying a severity level (Debug, Error, Warning, Info) and a tag identifying its source. A real, growing app produces a genuinely large volume of log output — filtering by tag, by package/process, by log level, or by a free-text search isn't optional polish at any real scale; it's the only practical way to find the specific line that matters among everything else being logged at the same time.

Reading a Stack Trace in Logcat

An uncaught exception prints its full stack trace to Logcat at the Error level. Reading it top to bottom: the exception's own type and message come first, followed by the call chain that led to it. The topmost frame that actually belongs to your own app's code — rather than a framework or library frame — is usually the most useful starting point, since it's the closest point in the call chain still under your own control.

Breakpoints & Stepping

Clicking a line's own gutter sets a breakpoint; running the app in Debug mode (rather than plain Run) means execution actually pauses there when reached. Once paused, three stepping actions control what happens next: Step Over runs the current line's own function call to completion without descending into it; Step Into descends into that called function's own code, line by line; Step Out finishes the current function entirely and returns control to whatever called it.

Inspecting Variables Live

While paused at a breakpoint, the Variables pane shows every variable currently in scope, with the ability to drill directly into an object's own fields rather than guessing at its contents. Evaluate Expression goes further: it runs an arbitrary expression or method call in that exact paused context, without needing to add a temporary Log statement and rerun the entire app just to check one value.

ToolShowsReach for it when
LogcatA running history of log output and stack tracesUnderstanding what already happened, over time
Breakpoints + steppingExecution paused at an exact lineWatching exactly how execution reaches a specific point
Variables pane / Evaluate ExpressionLive values at the current pause pointConfirming exact state without adding temporary logging
Two different debugging questions
Logcat and the debugger answer "what is happening, and why." The Profiler, covered next in Chapter 5, answers a genuinely different question — "how much resource is this using" — real-time CPU, memory, and network measurement rather than logic tracing. Knowing which of these two questions you're actually asking determines which tool is the right one to reach for first.
Adding more Log statements isn't the only, or always the fastest, way to debug
It's a common habit to debug purely by sprinkling Log statements through code and rerunning the app repeatedly to see new output — sometimes genuinely the right tool, but relying on it exclusively when a real debugger with breakpoints, live variable inspection, and Evaluate Expression is available is often much slower. For a bug that's hard to reproduce reliably, a breakpoint lets you inspect the exact state at the precise moment something goes wrong, without needing to guess in advance exactly what to log before rerunning the whole app again.

Hands-On Exercises

Exercise 1

A breakpoint is set on a line that calls a helper function you're confident is already working correctly. Which stepping action — Step Over, Step Into, or Step Out — would you use to continue past this line without spending time watching the helper function's own internals, and why?

📄 View solution
Exercise 2

A bug only happens intermittently and is hard to reproduce reliably. A teammate suggests adding several Log statements and rerunning the app repeatedly until it happens again. Using this chapter's own warning box, suggest an alternative approach and explain why it might be more effective here specifically.

📄 View solution
Exercise 3

An app crashes with an uncaught exception, and Logcat shows a stack trace with several frames from Android framework classes before reaching a frame from the app's own MainActivity class. Explain which frame is the best starting point for investigation, and why.

📄 View solution

Chapter 4 Quick Reference

  • Logcat — filterable log output by tag/level/process; a real necessity at any real app scale, not optional polish
  • Step Over (skip a call's internals), Step Into (descend into it), Step Out (finish the current function and return)
  • Variables pane/Evaluate Expression — inspect or compute live values at a paused breakpoint, no rerun needed
  • Logcat/debugging answer "what and why"; the Profiler (Chapter 5) answers "how much resource" — different questions, different tools
  • A real debugger is often faster than repeated Log-and-rerun cycles, especially for intermittent bugs