Tips and tricks to suppress bugs faster on Android

Original address: medium.com/androiddeve…

Http://medium.com/adt_dherma…

Published: June 13, 2020 -11 minutes to read

As developers, we all know that sometimes we spend more time in the debugger than we do in the code editor. With that in mind, I recently took the opportunity to see what tips and tips members of our Android Studio team have for speeding up debugging. I’ve collected some of the best ones that I think will save you time and are easy to incorporate into your debugging process.

While your application will likely be very different from the hypothetical game application example we use here, these debugging tips will apply to any application.

If you want to see a live demo, you can find a video version of this article on YouTube.

Log filtering and folding

I’ll start with that classic debugging tip: the printf statement. In the case of a game, its frame rate per second is recorded every second, along with the user’s final score at the end of each game. In the Logcat window, this is going to get.

There is a lot of information in the output that you might not care about, such as dates and thread ids. You can easily configure what is displayed. On the LogCAT toolbar, click the Settings icon. In the Configure LogCAT header dialog box, deselect the information you don’t want to see.

Now you can get cleaner, more relevant log output, like this.

However, this still leaves a lot of messy information, obsctering the high score information. To keep track of these messages, use logcat search. Enter some debugging information in the search to filter the Logcat window.

If this is a search you use often, you can save it by adding a custom filter from the Edit filter configuration.

Then, add the details of your filter.

Another way to reduce log clutter is to use the line feature, which groups and collapses similar rows. Select some text from the log project, right-click, and select Collapse lines like this.

When the console dialog opens, click OK and a similar message containing the selected text is collapsed.

If you need to view the information later, you can click on the lines to expand them. There are also some grooved handles that allow you to unfold and fold folded rows.

Connection debugger

You usually start a debug session using the Debug button or menu option. However, if you start the application by running the application, you can attach the debugger to the running application without restarting it. To do this, click Attach the debugger to the Android process.

In the Choose Process dialog box, highlight the Process to which you want to attach the debugger, and then click OK. You will now start clicking on breakpoints just as you would in a debug session.

Move the breakpoint

If you find that you have set a breakpoint in an inappropriate place, instead of clearing and resetting the breakpoint, drag it to the line you care about. This is useful because it preserves the Settings on the breakpoint, including what I’ll mention next.

Conditional breakpoints

You may need to chase down an error related to a specific type of event in your application or game. For example, in a game you’re developing, you might want to stop when the player collides with an object that has exhausted its last bit of health. You set a breakpoint on the collision, but now the code stops on each collision. To avoid this, you can set a conditional breakpoint.

To set a conditional breakpoint, right-click on a breakpoint and add a condition. A condition can be any code expression equivalent to a Boolean value. When the code is typed, the breakpoint is activated if the expression is evaluated as true.

Here, in logic, you set a condition player.health == 1 when the player is about to collide with the object, which allows you to catch the player’s health before it drops to 0 when the player last collided with the object.

Independent breakpoint

It is not uncommon for an application’s code to be triggered from many different paths. If you have an error that only happens along a particular path, setting a breakpoint in your code can cause a lot of unnecessary breaks. To solve this problem, you can use dependency breakpoints that fire only after another specified breakpoint is hit. For example, you can create a breakpoint that fires only on the path you care about, and then use that as a dependency point so that your other breakpoints fire only on the path you are interested in.

To set a dependency breakpoint, right-click the second breakpoint and open the “More” menu. In “Disable until breakpoint is hit”, select the breakpoint you want to rely on.

You will notice that the breakpoint icon changes.

Now, you only stop here if you hit the previous breakpoint.

You can also use this feature when you have conditional breakpoints elsewhere, but you want to avoid copying and pasting the condition to a new location.

To suspend a thread

If you are debugging a multithreaded application, you will notice that breakpoints pause all threads by default. However, you probably don’t want this behavior. For example, maybe you want to verify that you can block on one thread while the rest of the application still works, or you want your UI to continue rendering while investigating background tasks. To suspend only the current thread, turn on the breakpoint option and select the thread in the pause Settings.

Evaluation and recording

Sometimes, you want to see some information related to the state of your application, rather than staying at a breakpoint. You might add printlns to your code to do this. Instead of using this method that requires recompilation, you can use the breakpoints themselves to evaluate and record.

To do this, disable Suspend, enable Evaluate, and log in the breakpoint option.

Now you can add any code expression and it will be evaluated and logged to the console.

If you just want to quickly verify that your Breakpoint was triggered and don’t care about the details, you can use a “Breakpoint hit “message to record that your Breakpoint was hit. There is even a quick way to create such breakpoints: simply press Shift and click in the slot.

Disable breakpoints

If you want to disable breakpoints quickly, instead of right-clicking and deselecting “Enabled,” you can toggle breakpoints on and off by middle clicking, or by pressing Alt (Option on Mac) and left-clicking.

A breakpoint set

You’ve been working on a bug, creating breakpoints, and find yourself making little progress. So you move on to another bug, but soon you start hitting breakpoints on the first bug. Soon, however, you start hitting breakpoints on the first bug. Hitting irrelevant breakpoints can be frustrating and take you out of the debugging process.

You can make your life easier by using breakpoint groups.

When you hit the first unneeded breakpoint, right click and open “More”. You should now see a list of all breakpoints. Multiple select all breakpoints associated with your first bug.

Right-click the selected breakpoint and click Move to Group, then create a new one. Name the group, perhaps after the bug you’re working on. Now you can easily toggle all breakpoints with one click.

In addition, when you are done with this BUG, you can use groups to remove all breakpoints.

Frame drop

Sometimes, when walking through paused code, you might accidentally step on a method instead of entering it. If you’re running Android 10 or later, you can now trace back by clicking Drop Frame in the debugger toolbar.

This feature pulls you out of the current method and brings you back to the point before the method started, giving you a second chance to step into the method.

This feature is not a time machine. If you’re in the middle of a long function and it has done a lot of intermediate work — for example, modifying the state of the current class — that work won’t be undone when you drop the framework.

Tag object

Sometimes you want to focus on the life cycle of a particular class instance, as in this example, where the hash code for a project is @10140.

You might be tempted to take out a piece of paper and write down 10140 so you can identify the object when it comes up again. But, alternatively, you can right-click the item, click on the mark object, and label it.

Now, in any debug window, wherever the tag object appears, there is a label and it is easy to find. In this case, we’re going to mark this object as “myItem”.

This is even better for tracking an object and being able to see it in the Watches window, even if you’re in a completely different context and the item can’t be reached any other way. Wherever you are, as soon as you hit a breakpoint, in the Watches window, add your label after “_DebugLabel “(don’t worry about remembering this, it will do it automatically).

You can now follow a class item anywhere in the Watches window to see its status.

You can also combine this functionality with conditional breakpoints. For example, you can set a breakpoint, right-click on it, and set conditions to examine label objects.

Now, instead of stepping more than one breakpoint until a specific project instance is in scope, the code will break for you in the right place.

Evaluation expression

While variables and watch Windows are useful for monitoring explicit values, sometimes you want to explore your code more freely, and that’s where evaluating expressions come in. When you are at a breakpoint, you can access this function from the Evaluate Expression in the debugger toolbar.

In the “expression” text input box, enter any expression, press the “evaluation” key to evaluate. In addition, if you evaluate an object, you can browse the object in the results section after the evaluation.

The evaluation expression dialog may open in single-line mode. You can easily expand it to multiple lines by clicking expand.

Now you can enter complex multi-line expressions. These expressions can include variables, if statements, and so on.

Application of change

When you have a conditional breakpoint where an expression is evaluated, the debugger still evaluates even if you don’t stop at the breakpoint. If you run some code in a very tight loop, such as animation processing in a game, this can cause the application to stall. While conditional breakpoints are useful, this can be an edge case and you can’t rely on them.

One way to get around this problem is to add conditional expressions to your code and use no-action expressions so you can attach breakpoints.

Once you’ve done that, you might decide to restart your application and click Debug. However, instead of doing this, you can use Apply Code Changes when running Android 8 and above.

Your code has now been patched with embedded expressions. However, you will see the method you updated marked Obsolete in the Frames window.

This is because the new code has been patched, but your debugger still points to the old code. You can use the Drop Frame function to get out of the old method and into the new method.

Although we don’t need it in this case, there is a second option, Apply Changes and Restart Activity. Unlike Apply Code Changes, this option also restarts the activity, which is useful if you have modified the layout resource, or if the Code you are trying to debug is, for example, in the onCreate method.

Analysis of the stacktrace

Despite these tips and tricks, unfortunately, you may have bugs in your code and receive bug reports. By the time you receive these bug reports, the reporter may have included a text copy of the exception’s stack. You can convert this information into meaningful information in Android Studio using the Analyze Stack Trace or Thread Dump from the Analyze menu.

This tool provides a place to paste a stack trace, but it will automatically populate any text in your clipboard.

Click OK, and a fully annotated version of the stack trace is added to the console.

You can see at a glance which code is in your code base (highlighted in blue above) and which code you might not need to pay attention to (highlighted in gray). Also, you can click on links to quickly jump through your code base.

The last word

These are just a few tips and tricks you can use to speed up debugging. A few that we don’t have time to cover in detail here include.

  • In debug mode, click on the row number in the ditch to run to that row.
  • Ctrl+ Drag copies a breakpoint.
  • You can set breakpoints on the closing brackets of a function.
  • You can set breakpoints (called “field watch points”) on fields and properties.
  • You can set a breakpoint on an interface method that breaks all of its implementations.

There are also some links related to this topic that you may want to check out, including.

  • A data view that controls how data is displayed in the debugger
  • How to use and understand the “Expenses” TAB
  • APK debugging
  • IntelliJ IDEA debugging code
  • Android Studio tips and tricks for I/O 19