Android fundamentals 03.1: The debugger

1. Welcome


In previous practicals you used the Log class to print information to the system log, which appears in the Logcat pane in Android Studio when your app runs. Adding logging statements to your app is one way to find errors and improve your app's operation. Another way is to use the debugger built into Android Studio.

In this practical you learn how to debug your app in an emulator and on the device, set and view breakpoints, step through your code, and examine variables.

What you should already know

You should be able to:

  • Create an Android Studio project.
  • Use the layout editor to work with EditText and Button elements.
  • Build and run your app in Android Studio, on both an emulator and on a device.
  • Read and analyze a stack trace, including last on, first off.
  • Add log statements and view the system log (the Logcat pane) in Android Studio.

What you'll learn

  • How to run your app in debug mode in an emulator or on a device.
  • How to step through the execution of your app.
  • How to set and organize breakpoints.
  • How to examine and modify variables in the debugger.

What you'll do

  • Build the SimpleCalc app.
  • Set and view breakpoints in the code for SimpleCalc.
  • Step through your code as it runs.
  • Examine variables and evaluate expressions.
  • Identify and fix problems in the sample app.

2. App Overview

The SimpleCalc app has two EditText elements and four Button elements. When you enter two numbers and click a Button, the app performs the calculation for that Button and displays the result.


3. Task 1: Explore the SimpleCalc project and app

For this practical you won't build the SimpleCalc app yourself. The complete project is available at SimpleCalc. In this task you open the SimpleCalc project in Android Studio and explore some of the app's key features.

1.1 Download and Open the SimpleCalc Project

  1. Download SimpleCalc and unzip the file.
  2. Start Android Studio and select File > Open.
  3. Navigate to the folder for SimpleCalc, select that folder file, and click OK. The SimpleCalc project builds.
  4. Open the Project > Android pane if it is not already open.

1.2 Explore the Layout

  1. Open activity_main.xml.
  2. Click the Text tab to see the XML code.
  3. Click the Preview tab to see a preview of the layout.

Examine the layout XML code and design and note the following:

  • The layout contains two EditText elements for the input, four Button elements for the calculations, and one TextView to display the result.
  • Each calculation Button has its own android:onClick click handler (onAdd, OnSub, and so on.)
  • The TextView for the result does not have any text in it by default.
  • The two EditText elements have the android:inputType attribute and the value "numberDecimal". This attribute indicates that the EditText accepts only numbers as input. The keyboard that appears on-screen will only contain numbers. You will learn more about input types for EditText elements in a later practical.


1.3 Explore the app code

  1. Expand the app > java folder in the Project > Android pane. In addition to the MainActivity class, this project also includes a utility Calculator class.
  2. Open Calculator and examine the code. Note that the operations the calculator can perform are defined by the Operator enum, and that all of the operation methods are public.
  3. Open MainActivity, and examine the code and comments.

Note the following:

  • All of the defined android:onClick click handlers call the private compute() method, with the operation name as one of the values from the Calculator.Operator enumeration.
  • The compute() method calls the private method getOperand() (which in turn calls getOperandText()) to retrieve the number values from the EditText elements.
  • The compute() method then uses a switch on the operand name to call the appropriate method in the Calculator instance (mCalculator).
  • The calculation methods in the Calculator class perform the actual arithmetic and return a value.
  • The last part of the compute() method updates the TextView with the result of the calculation.

1.4 Run the app

Run the app and follow these steps:

  1. Enter both integer and floating-point values for the calculation.
  2. Enter floating-point values with large decimal fractions (for example, 1.6753456)
  3. Divide a number by zero.
  4. Leave one or both of the EditText elements empty, and try any calculation.
  5. Click the Logcat tab at the bottom of the Android Studio window to open the Logcat pane (if it is not already open). Examine the stack trace at the point where the app reports an error.

If one or both of the EditText elements in SimpleCalc are empty, the app reports an exception, as shown in the figure below, and the system log displays the state of the execution stack at the time the app produced the error. The stack trace usually provides important information about why an error occurred.

Stack trace in the Logcat pane for the SimpleCalc App

4. Task 2: Run SimpleCalc in the debugger

In this task you'll get an introduction to the debugger in Android Studio, and learn how to set a breakpoint and run your app in debug mode.

2.1 Start and run your app in debug mode

  1. In Android Studio, select Run > Debug app or click the Debug icon a916a2f8666fcdd6.png in the toolbar.
  2. If your app is already running, you will be asked if you want to restart your app in debug mode. Click Restart app.

Android Studio builds and runs your app on the emulator or on the device. Debugging is the same in either case. While Android Studio is initializing the debugger, you may see a message that says "Waiting for debugger" on the device before you can use your app.

  1. Click the Debug tab at the bottom of the Android Studio window to show the Debug pane (or choose View > Tool Windows > Debug). The Debugger tab in the pane should already be selected, showing the Debugger pane.

2.2 Set a breakpoint

A breakpoint is a place in your code where you want to pause the normal execution of your app to perform other actions such as examining variables or evaluating expressions, or executing your code line by line to determine the causes of runtime errors. You can set a breakpoint on any executable line of code.

  1. Open MainActivity, and click in the fourth line of the compute() method (the line just after the try statement).
  2. Click in the left gutter of the editor pane at that line, next to the line numbers. A red dot appears at that line, indicating a breakpoint. The red dot includes a check mark if the app is already running in debug mode.

As an alternative, you can choose Run > Toggle Line Breakpoint or press Control-F8 (Command-F8 on a Mac) to set or clear a breakpoint at a line.

Setting a breakpoint while running the app in debug mode

If you click a breakpoint by mistake, you can undo it by clicking the breakpoint. If you click a line of code that is not executable, the red dot includes an "x" and a warning appears that the line of code is not executable.

  1. In the SimpleCalc app, enter numbers in the EditText elements and click one of the calculate Button elements.

The execution of your app stops when it reaches the breakpoint you set, and the debugger shows the current state of your app at that breakpoint as shown in the figure below.

Debug pane in Android Studio

The figure above shows the Debug pane with the Debugger and Console tabs. The Debugger tab is selected, showing the Debugger pane with the following features:

  1. Frames tab: Click to show the Frames pane with the current execution stack frames for a given thread. The execution stack shows each class and method that have been called in your app and in the Android runtime, with the most recent method at the top.

Click the Threads tab to replace the Frames pane with the Threads pane. Your app is currently running in the main thread, and the app is executing the compute() method in MainActivity.

  1. Watches button: Click to show the Watches pane within the Variables pane, which shows the values for any variable watches you have set. Watches allow you to keep track of a specific variable in your program, and see how that variable changes as your program runs.
  2. Variables pane: Shows the variables in the current scope and their values. At this stage of your app's execution, the available variables are: this (for the Activity), operator (the operator name from Calculator.Operator that the method was called from), as well as the global variables for the EditText elements and the TextView. Each variable in this pane has an expand icon to expand the list of object properties for the variable. Try expanding a variable to explore its properties.

2.3 Resume your app's execution

Resume your app's execution by choosing Run > Resume Program, or click the Resume or click the Resume [ICON HERE] icon on the left side of the debugger window. [IMAGEINFO]: ic_resume.png, Resume icon icon on the left side of the debugger window.

The SimpleCalc app continues running, and you can interact with the app until the next time the code execution arrives at the breakpoint.

2.4 Debug a running app

If your app is already running on a device or emulator, and you decide you want to debug that app, you can switch an already running app to debug mode.

  1. Run the SimpleCalc app normally, with the Run with the Run [ICON HERE] icon. [IMAGEINFO]: ic_run.png, Run icon icon.
  2. Select Run > Attach debugger to Android process or click the Attach Attach icon icon in the toolbar.
  3. Select your app's process from the dialog that appears (shown below). Click OK.

Choose process dialog

The Debug pane appears with the Debugger pane open, and you can now debug your app as if you had started it in debug mode.

5. Task 3: Explore debugger features

In this task we'll explore the various features in the Android Studio debugger, including executing your app line by line, working with breakpoints, and examining variables.

3.1 Step through your app's execution

After a breakpoint, you can use the debugger to execute each line of code in your app one at a time, and examine the state of variables as the app runs.

  1. Debug your app in Android Studio, with the breakpoint you set in the last task.
  2. In the app, enter numbers in both EditText elements, and click the Add button.

Your app's execution stops at the breakpoint that you set earlier, and the Debugger pane shows the current state of the app. The current line is highlighted in your code.

  1. Click the Step Over Step Over icon button at the top of the debugger window.

The debugger executes the current line in the compute() method (where the breakpoint is, the assignment for operandOne), and the highlight moves to the next line in the code (the assignment for operandTwo). The Variables pane updates to reflect the new execution state, and the current values of variables also appear after each line of your source code in italics.

You can also use Run > Step Over, or press F8, to step over your code.

  1. At the next line (the assignment for operandTwo), click the Step Into click the Step Into [ICON HERE] icon. [IMAGEINFO]: ic_step-into.png, Step Into icon icon.

Step Into jumps into the execution of a method call in the current line (compared to just executing that method and remaining on the same line). In this case, because that assignment includes a call to getOperand(), the debugger scrolls the MainActivity code to that method definition.

When you step into a method, the Frames pane updates to indicate the new frame in the call stack (here, getOperand()), and the Variables pane shows the available variables in the new method scope. You can click any of the lines in the Frames pane to see the point in the previous stack frame where the method was invoked.

Debugger pane after clicking Step Into

You can also use Run > Step Into, or F7, to step into a method.

  1. Click Step Over and all the panels update with the new information. [IMAGEINFO]: ic_step-over.png, Step Over icon to run each of the lines in getOperand(). Note that when the method completes the debugger returns you to the point where you first stepped into the method, and all the panels update to show the new information.
  2. Click Step Over twice to move the execution point to the first line inside the case statement for ADD.
  3. Click Step Into Step Into icon.

The debugger executes the appropriate method defined in the Calculator class, opens the file, and scrolls to the execution point in that class. Again, the various panes update to reflect the new state.

  1. Use the Step Out Step Out icon icon to execute the remainder of that calculation method and pop back out to the compute() method in MainActivity. You can then continue debugging the compute() method from where you left off.

You can also use Run > Step Out or press Shift-F8 to step out of a method execution.

3.2 Work with Breakpoints

Use breakpoints to indicate where in your code you want to interrupt your app's execution to debug that portion of that app.

  1. Find the breakpoint you set in the last task—at the start of the compute() method in MainActivity.
  2. Add a breakpoint to the start of the switch statement.
  3. Right-click on that new breakpoint to enter a condition, as shown in the figure below, and enter the following test in the Condition field:

(operandOne == 42)||(operandTwo == 42)

Entering a test in the Condition field

  1. Click Done.

This second breakpoint is a conditional breakpoint. The execution of your app will only stop at this breakpoint if the test in the condition is true. In this case, the expression is only true if one or the other operands you entered is 42. You can enter any Java expression as a condition as long as it returns a boolean.

  1. Run your app in debug mode (Run > Debug), or click Resume or click Resume [ICON HERE] if it is already running. In the app, enter two numbers other than 42 and click the Add button. Execution halts at the first breakpoint in the compute() method.[IMAGEINFO]: ic_resume.png, Resume icon if it is already running. In the app, enter two numbers other than 42 and click the Add button. Execution halts at the first breakpoint in the compute() method.
  2. Click Resume to continue debugging the app. Observe that execution did not stop at your second breakpoint, because the condition was not met.
  3. In the app, enter 42 in the first EditText and click any Button. Click Resume to resume execution after the first breakpoint. Observe that the second breakpoint at the switch statement—the conditional breakpoint—halts execution because the condition was met.
  4. Right-click (or Control-click) the first breakpoint in compute() and uncheck Enabled. Click Done. Observe that the breakpoint icon now has a green dot with a red border.

Disabling a breakpoint enables you to temporarily "mute" that breakpoint without actually removing it from your code. If you remove a breakpoint altogether you also lose any conditions you created for that breakpoint, so disabling it is often a better choice.

You can also mute all breakpoints in your app at once with the Mute Breakpoints Mute Breakpoints Icon icon.

  1. Click View Breakpoints View Breakpoints icon on the left edge of the debugger window. The Breakpoints window appears.

The Breakpoints window enables you to see all the breakpoints in your app, enable or disable individual breakpoints, and add additional features of breakpoints including conditions, dependencies on other breakpoints, and logging.

Breakpoints window

To close the Breakpoints window, click Done.

3.3 Examine and modify variables

The Android Studio debugger lets you examine the state of the variables in your app as that app runs.

  1. Run the SimpleCalc app in debug mode if it is not already running.
  2. In the app, enter two numbers, one of them 42, and click the Add button.

The first breakpoint in compute() is still muted. Execution stops at the second breakpoint (the conditional breakpoint at the switch statement), and the debugger appears.

  1. Observe in the Variables pane that the operandOne and operandTwo variables have the values you entered into the app.

Variables at the breakpoint

  1. The this variable is a MainActivity object. Click the expand icon to see a list of member variables of that object. Click the expand icon again to close the list.
  2. Right-click (or Control-click) the operandOne variable in the Variables pane, and select Set Value.

Setting a variable at the breakpoint

  1. Change the value of operandOne to 10 and press Return.
  2. Change the value of operandTwo to 10 in the same way and press Return.
  3. Observe that the result in the app is now based on the variable values you changed in the debugger; for example, since you clicked the Add Button in Step 2, the result in the app is now 20.
  4. Click the Resume icon to continue running your app.
  5. In the app, the original entries (including 42) are preserved in the EditText elements. (Their values were changed only in the debugger.) Click the Add button. Execution halts at the breakpoint again.
  6. Click the Evaluate Expression b753eea839a664dc.png icon, or select Run > Evaluate Expression. You can also right-click (or Control-click) any variable and choose Evaluate Expression.

The Evaluate Code Fragment window appears. Use it to explore the state of variables and objects in your app, including calling methods on those objects. You can enter any code into this window.

Evaluate Code Fragment window

  1. Type the statement mOperandOneEditText.getHint(); into the top field of the Evaluate Code Fragment window (as shown in the figure above), and click Evaluate.
  2. The Result field shows the result of that expression. The hint for this EditText is the string "Type Operand 1", as was originally defined in the XML for that EditText.

The result you get from evaluating an expression is based on the app's current state. Depending on the values of the variables in your app at the time you evaluate expressions, you may get different results.

Note also that if you use Evaluate Expression to change the values of variables or object properties, you change the running state of the app.

  1. Click Close to close the Evaluate Code Fragment window.

6. Coding challenge

Challenge: At the end of Task 1, you tried running the SimpleCalc app with no value in one of the EditText elements, resulting in an error. Use the debugger to step through the execution of the code and determine precisely why this error occurs. Fix the bug that causes this error.

7. Summary

  • View logging information in Android Studio by clicking the Logcat tab.
  • Run your app in debug mode by clicking the Debug icon or choosing Run > Debug app.
  • Click the Debug tab to show the Debug pane. Click the Debugger tab in the Debug pane to show the Debugger pane (if it is not already selected).
  • The Debugger pane shows (stack) Frames, Variables in a specific frame, and Watches (active tracking of a variable while the program runs).
  • A breakpoint is a place in your code where you want to pause normal execution of your app to perform other actions. Set or clear a debugging breakpoint by clicking in the left gutter of the editor window immediately next to the target line.

8. Related concept

The related concept documentation is in 3.1: The Android Studio debugger.

9. Learn more

Android Studio documentation:


10. Homework

This section lists possible homework assignments for students who are working through this codelab as part of a course led by an instructor. It's up to the instructor to do the following:

  • Assign homework if required.
  • Communicate to students how to submit homework assignments.
  • Grade the homework assignments.

Instructors can use these suggestions as little or as much as they want, and should feel free to assign any other homework they feel is appropriate.

If you're working through this codelab on your own, feel free to use these homework assignments to test your knowledge.

Build and run an app

Open the SimpleCalc app.

  1. In MainActivity, place a breakpoint on the first line of the onAdd() method.
  2. Run the app in the debugger. Perform an add operation in the app. The execution stops at the breakpoint.
  3. Click Step Into to follow the execution of the app step by step. Note that Step Into opens and executes files from the Android framework, enabling you to see how Android itself operates on your code.
  4. Examine how the Debug pane changes as you step through the code for the current stack frame and local variables.
  5. Examine how the code itself in the editor pane is annotated as each line is executed.
  6. Click Step Out to return back to your app if the execution stack gets too deep to understand.

Answer these questions

Question 1

Run the SimpleCalc app without the debugger. Leave one or both of the EditText elements empty, and try any calculation. Why did the error occur?

  • java.lang.NumberFormatException: empty String
  • W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED
  • The app may be doing too much work on its main thread.
  • The code cache capacity was increased to 128KB.

Question 2

Which function do you perform in the Debug pane in order to execute the current line where the breakpoint is, and then stop at the next line in the code? Choose one:

  • Step Into
  • Step Over
  • Step Out
  • Resume

Question 3

Which function do you perform in the Debug pane in order to jump to the execution of a method call from the current line where the breakpoint is? Choose one:

  • Step Into
  • Step Over
  • Step Out
  • Resume

Submit your app for grading

Guidance for graders

No app to submit for this homework assignment.

11. Next codelab

To find the next practical codelab in the Android Developer Fundamentals (V2) course, see Codelabs for Android Developer Fundamentals (V2).

For an overview of the course, including links to the concept chapters, apps, and slides, see Android Developer Fundamentals (Version 2).