Ensure High-Quality Android Code With Static Analysis Tools

Ensure High-Quality Android Code With Static Analysis Tools

In today's tutorial, we'll learn about how to ensure high-quality Android code in our projects using some static code analysis tools for Java. We'll look at Checkstyle, FindBugs, PMD, and Android Studio Lint—all of them free and open source!

What Are Static Code Analysis Tools?

These are tools that parse and analyse your source code without actually executing it. The goal is to find potential vulnerabilities such as bugs and security flaws. A popular free static code analyser such as FindBugs checks your code against a set of rules which your code should adhere to—if the code doesn't follow these rules, it's a sign that something may be wrong. Think of static code analysis tools as an additional compiler that is run before the final compilation into the system language.  

Many software companies are requiring projects to pass static code analysis tests, in addition to doing code reviews and unit testing in the build process. Even maintainers of open-source projects often include one or more static code analysis steps in the build process. So learning about static analysis is an important step in writing quality code. Be aware that static code analysis—also known as "white-box" testing—should not be seen as a replacement for unit testing of your source code.

In this tutorial, we're going to learn about some popular static analysis tools that are available for Android and Java. But first, let's see some of the benefits of using static analysis.

Benefits

  • Helps detect potential bugs that even unit or manual testing might have missed.
  • Defines project-specific rules. For example, static analysis as part of the build chain helps newcomers get up to speed with the code standards of their new team.
  • Helps you improve your knowledge of a new language.
  • Scans your whole project, including files that you might not have ever read.

Setup

All the code analysis tools we'll learn about in this tutorial are available as Gradle plugins, so we can create individual Gradle tasks for each of them. Let's use a single Gradle file that will include them all. But before that, let's create a folder that will contain all of our files for the static code analysis. 

Open Android Studio and inside the app module (in Project view), create a new folder and name it code_quality_tools. This folder will contain the XML files for the code analysis tools, and it will also have a Gradle file, quality.gradle, which will run our static analysis tasks. 

Android studio project structure screenshot

Finally, visit your build.gradle in the app module folder and include this line at the end of the file:

Here, our quality.gradle Gradle script is being applied with a reference to its local file location. 

Checkstyle

Given rules you specify in an XML file to enforce a coding standard for your project, Checkstyle enforces those rules by analysing your source code and compares them against known coding standards or conventions. 

Checkstyle is an open-source tool that is actively maintained by the community. This means you can create your own custom checks or modify existing ones to suit your needs. For example, Checkstyle can run a check on the constant names (final, static, or both) in your classes. If your constant names do not stick to a rule of being in uppercase with words separated by an underscore, the problem will be flagged in the final report. 

Integrating Checkstyle

I'll show you how to integrate Checkstyle into our Android Studio project and demonstrate a practical example.

First, we need to create our coding rules. Inside checkstyle.xml, we create some Checkstyle configuration rules that will be run against our code.

In the above code, we include the rules or checks we want Checkstyle to validate in our source code. One rule is AvoidStarImport which, as the name says, checks if your source code included an import statement like java.util.*. (Instead, you should explicitly specify the package to import, e.g. java.util.Observable.) 

Some rules have properties, which we can set just like we did for ParameterNumber—this limits the number of parameters of a method or constructor. By default, the property max is 7, but we changed it to 6 instead. Take a look at some of the other checks on the Checkstyle website.

To run this check, we need to create a Gradle task. So visit the quality.gradle file and create a task called checkstyle:

Notice that in the code above, we first applied the Checkstyle Gradle plugin. We gave it a description and added it to an already predefined Gradle group called verification. 

The key properties of the Checkstyle Gradle task we are concerned with are: 

  • configFile: the Checkstyle configuration file to use.
  • IgnoreFailures: whether or not to allow the build to continue if there are warnings.
  • include: the set of include patterns.
  • exclude: the set of exclude patterns. In this case, we don't scan generated classes. 

Finally, you can run the Gradle script by visiting the Gradle tool window on Android Studio, opening the verification group, and then clicking on checkstyle to run the task. 

Gradle toolbar open to run checkstyle task

Another way is to use the command line: 

After the task has finished running, a report will be generated, which is available at app module > build > reports > checkstyle. You can open checkstyle.html to view the report. 

Android Studio Checkstyle report folder location

Checkstyle plugin is freely available for Android Studio or IntelliJ IDEA. It offers real-time scanning of your Java files. 

PMD

PMD is another open-source code analysis tool that analyzes your source code. It finds common flaws like unused variables, empty catch blocks, unnecessary object creation and so on. PMD has many rule sets you can choose from. An example of a rule which is part of the Design Rules set is:

  • SimplifyBooleanExpressions: avoid unnecessary comparisons in boolean expressions which complicate simple code. An example: 

PMD is configured with the pmd.xml file. Inside it, we'll include some configuration rules such as the ones for Android, Naming, and Design

As we did for Checkstyle, we also need to create a PMD Gradle task for the check to be executed inside the quality.gradle file. 

PMD is also available as a Gradle plugin

The key properties of the task we've created are: 

  • ruleSetFiles: The custom rule set files to be used.
  • source: The source for this task.
  • reports: The reports to be generated by this task.

Finally, you can run the Gradle script by visiting the Gradle tool window, opening the verification group folder, and then clicking on pmd to run the task. Or you can run it via the command line:

A report will also be generated after the execution of the task which is available at app module > build > reports > pmd. There is also a PMD plugin available for IntelliJ or Android Studio for you to download and integrate if you want. 

FindBugs

FindBugs is another free static analysis tool which analyses your class looking for potential problems by checking your bytecodes against a known list of bug patterns. Some of them are:

  • Class defines hashCode() but not equals(): A class implements the hashCode() method but not equals()—therefore two instances might be equal but not have the same hash codes. This falls under the bad practice category. 
  • Bad comparison of int value with long constant: The code is comparing an int value with a long constant that is outside the range of values that can be represented as an int value. This comparison is vacuous and possibly will yield an unexpected result. This falls under the correctness category. 
  • TestCase has no tests: class is a JUnit TestCase but has not implemented any test methods. This pattern is also under the correctness category. 

FindBugs is an open-source project, so you can view, contribute or monitor the progress of the source code on GitHub

In the findbugs-exclude.xml file, we want to prevent FindBugs from scanning some classes (using regular expressions) in our projects, such as auto-generated resource classes and auto-generated manifest classes. Also, if you use Dagger, we want FindBugs not to check the generated Dagger classes. We can also tell FindBugs to ignore some rules if we want. 

And finally, we'll include the findbugs task in quality.gradle:

In the first line above, we applied FindBugs as a Gradle Plugin and then created a task called findbugs. The key properties of the findbugs task we are really concerned with are: 

  • classes: the classes to be analyzed.
  • effort: the analysis effort level. The value specified should be one of mindefault, or max.  Be aware that higher levels increase precision and find more bugs at the cost of running time and memory consumption.
  • reportLevel: the priority threshold for reporting bugs. If set to low, all bugs are reported. If set to medium (the default), medium and high priority bugs are reported. If set to high, only high priority bugs are reported.
  • excludeFilter: the filename of a filter specifying bugs to exclude from being reported, which we have created already. 

You can then run the Gradle script by visiting the Gradle tool window, opening the verification group folder, and then clicking on findbugs to run the task. Or launch it from the command line:

A report will also be generated when the task has finished executing. This will be available at app module > build > reports > findbugs. The FindBugs plugin is another freely available plugin for download and integration with either IntelliJ IDEA or Android Studio.

Android Lint

Lint is another code analysis tool, but this one comes with Android Studio by default. It checks your Android project source files for potential bugs and optimizations for correctness, security, performance, usability, accessibility, and internationalization. 

To configure Lint, you have to include the lintOptions {} block in your module-level build.gradle file:

The key Lint options we are concerned with are: 

  • abortOnError: whether lint should set the exit code of the process if errors are found.
  • quiet: whether to turn off analysis progress reporting.
  • lintConfig: the default configuration file to use.

Your lint.xml file can include issues you want Lint to ignore or modify, such as the example below:

You can run Lint manually from Android Studio by clicking on the Analyze menu, choosing Inspect Code... (the inspection scope is the whole project), and then clicking on the OK button to proceed.

Android studio inspect code menu
Android Studio lint inspect whole project code dialog

You can also run Lint by visiting the Gradle tool window, opening the verification group, and then clicking on lint. Finally, you can run it via the command line.

On Windows:

On Linux or Mac:

A report will also be generated when the task has finished executing, which is available at app module > build > outputs > lint-results.html.

Bonus: StrictMode

StrictMode is a developer tool that helps prevent developers of your project doing any accidental flash I/O or network I/O on the main thread, because this can lead to the app being sluggish or unresponsive. It also helps in preventing ANR (App Not Responding) dialogs from showing up. With StrictMode issues corrected, your app will become more responsive and the user will enjoy a smoother experience. StrictMode uses two sets of policies to enforce its rules:

  • VM Policies: guards against bad coding practices such as not closing SQLiteCursor objects or any Closeable object that was created. 
  • Thread Policies: looks out for operations such as flash I/O and network I/O being performed on the main application thread instead of on a background thread. 

The code above can be either in your Application, Activity, or other application component's onCreate() method. 

You can learn more about StrictMode here on Envato Tuts+. 

A sample Android project implementing all of the above including rule sets of the tools for a typical Android project can be found in this post's GitHub repo.

Conclusion

In this tutorial, you learned about how to ensure high-quality Android code using static code analysis tools: what they are, benefits of using them, and how to use Checkstyle, FindBugs, Lint, PMD, and StrictMode in your application. Go ahead and give these tools a try—you might discover some problems in your code that you never expected.

In the meantime, check out some of our other courses and tutorials on Android app development!

Source: Tuts Plus

About the Author