1. Welcome
Introduction
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
andButton
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
- Download SimpleCalc and unzip the file.
- Start Android Studio and select File > Open.
- Navigate to the folder for SimpleCalc, select that folder file, and click OK. The SimpleCalc project builds.
- Open the Project > Android pane if it is not already open.
1.2 Explore the Layout
- Open activity_main.xml.
- Click the Text tab to see the XML code.
- 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, fourButton
elements for the calculations, and oneTextView
to display the result. - Each calculation
Button
has its ownandroid: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 theandroid:inputType
attribute and the value"numberDecimal"
. This attribute indicates that theEditText
accepts only numbers as input. The keyboard that appears on-screen will only contain numbers. You will learn more about input types forEditText
elements in a later practical.
1.3 Explore the app code
- Expand the app > java folder in the Project > Android pane. In addition to the
MainActivity
class, this project also includes a utilityCalculator
class. - 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 arepublic
. - Open MainActivity, and examine the code and comments.
Note the following:
- All of the defined
android:onClick
click handlers call the privatecompute()
method, with the operation name as one of the values from theCalculator.Operator
enumeration. - The
compute()
method calls theprivate
methodgetOperand()
(which in turn callsgetOperandText()
) to retrieve the number values from theEditText
elements. - The
compute()
method then uses aswitch
on the operand name to call the appropriate method in theCalculator
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 theTextView
with the result of the calculation.
1.4 Run the app
Run the app and follow these steps:
- Enter both integer and floating-point values for the calculation.
- Enter floating-point values with large decimal fractions (for example, 1.6753456)
- Divide a number by zero.
- Leave one or both of the
EditText
elements empty, and try any calculation. - 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.
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
- In Android Studio, select Run > Debug app or click the Debug icon
in the toolbar.
- 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.
- 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.
- Open MainActivity, and click in the fourth line of the
compute()
method (the line just after thetry
statement). - 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.
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.
- In the SimpleCalc app, enter numbers in the
EditText
elements and click one of the calculateButton
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.
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:
- 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
.
- 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.
- 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 theActivity
),operator
(the operator name fromCalculator.Operator
that the method was called from), as well as the global variables for theEditText
elements and theTextView
. 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 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.
- Run the SimpleCalc app normally, with the Run
icon.
- Select Run > Attach debugger to Android process or click the Attach
icon in the toolbar.
- Select your app's process from the dialog that appears (shown below). Click OK.
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.
- Debug your app in Android Studio, with the breakpoint you set in the last task.
- 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.
- Click the Step Over
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.
- At the next line (the assignment for
operandTwo
), click the Step Intoicon.
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.
You can also use Run > Step Into, or F7, to step into a method.
- Click Step Over
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. - Click Step Over twice to move the execution point to the first line inside the
case
statement forADD
. - Click Step Into
.
The debugger executes the appropriate method defined in the Calculator
class, opens the Calculator.java
file, and scrolls to the execution point in that class. Again, the various panes update to reflect the new state.
- Use the Step Out
icon to execute the remainder of that calculation method and pop back out to the
compute()
method inMainActivity
. You can then continue debugging thecompute()
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.
- Find the breakpoint you set in the last task—at the start of the
compute()
method inMainActivity
. - Add a breakpoint to the start of the
switch
statement. - 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)
- 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
.
- Run your app in debug mode (Run > Debug), or click Resume
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. - Click Resume to continue debugging the app. Observe that execution did not stop at your second breakpoint, because the condition was not met.
- In the app, enter 42 in the first
EditText
and click anyButton
. Click Resume to resume execution after the first breakpoint. Observe that the second breakpoint at theswitch
statement—the conditional breakpoint—halts execution because the condition was met. - 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 icon.
- Click View Breakpoints
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.
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.
- Run the SimpleCalc app in debug mode if it is not already running.
- 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.
- Observe in the Variables pane that the
operandOne
andoperandTwo
variables have the values you entered into the app.
- The
this
variable is aMainActivity
object. Click the expand icon to see a list of member variables of that object. Click the expand icon again to close the list. - Right-click (or Control-click) the operandOne variable in the Variables pane, and select Set Value.
- Change the value of
operandOne
to 10 and press Return. - Change the value of
operandTwo
to 10 in the same way and press Return. - 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. - Click the Resume icon to continue running your app.
- 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. - Click the Evaluate Expression
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.
- Type the statement mOperandOneEditText.getHint(); into the top field of the Evaluate Code Fragment window (as shown in the figure above), and click Evaluate.
- 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 thatEditText
.
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.
- 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:
- Android Studio User Guide
- Debug Your App
- Write and View Logs
- Analyze a Stack Trace
- Android Debug Bridge
- Android Profiler
- Network Profiler
- CPU Profiler
- Traceview
Other:
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.
- In
MainActivity
, place a breakpoint on the first line of theonAdd()
method. - Run the app in the debugger. Perform an add operation in the app. The execution stops at the breakpoint.
- 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.
- Examine how the Debug pane changes as you step through the code for the current stack frame and local variables.
- Examine how the code itself in the editor pane is annotated as each line is executed.
- 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).