Improve Android code quality with static code analysis and runtime check:
It is recommended that you add these checks when you create a new project and fix the problems with every check-in (as part of your continuous integration process). Otherwise it would need enormous courage and patience when you face and fix the huge amount of errors.
build.gradle:apply from: '../quality/static_analysis.gradle'
git remote add analysis https://github.com/BrianSpace/Android-Quality-Essentials.gitbuild.gradle:apply from: '../analysis/quality/static_analysis.gradle'
android {
...
lintOptions {
// Turn off analysis progress reporting by lint
quiet true
// Stop the gradle build if errors are found
abortOnError true
// Do not ignore lint warnings
ignoreWarnings false
// Treat warnings as errors
warningsAsErrors true
// Ignore rules list
ignore 'GoogleAppIndexingWarning' // Remove this if the app support App Indexing
}
...
}
build.gradle: dependencies {
...
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.1'
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1'
testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1'
...
}Application class (and not forget to add to the manifest):public class AndroidQualityEssentialsApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
if (BuildConfig.DEBUG) {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectAll()
.penaltyDeath()
.build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectAll()
.penaltyDeath() // If violations are in Android itself or 3rd-party libs, use penaltyLog.
.build());
// Avoid the process dedicated to LeakCanary for heap analysis.
if (!LeakCanary.isInAnalyzerProcess(this)) {
LeakCanary.install(this);
}
}
...
}
}gradlew check in the console to start the static analysis.build/reports/ directory of the project in which you apply the static_analysis.gradle.The naming convention defined in the style rules does not allow single letter prefix for member field names like "mMember". But if you like this style, you can change the format property of the MemberName module to "^[a-z][a-zA-Z0-9]$". Or change to "^m[A-Z][a-zA-Z0-9]$" to force the "m" prefix.
For PMD rule UseUtilityClass, it will prompt to create Utility Class if your class has only static fields and methods. You just need to:
public final class FileUtil {
private static Context appContext;
private FileUtil() throws InstantiationException {
throw new InstantiationException("Utility class FileUtil should not be instantiated!");
}
public static void init(final Context context) {
appContext = context.getApplicationContext();
}
/**
* Get available cache directory. Prefer external over internal.
*/
@NonNull
public static File getAvailableCacheDir() {
final File externalCacheDir = appContext.getExternalCacheDir();
return externalCacheDir == null ? appContext.getCacheDir() : externalCacheDir;
}
}All the static analysis rules are best practices from people's past experience, but they are not always truth that cannot be broken. Some of the PMD rules need to be based on your own preferences:
ItemTypeT, for better readability. You can remove it from the "exclude" list if you like the single letter naming.Naming conventions are defined in the quality/checkstyle/naming_convention.xml file. The following rules are defined:
You can modify the regular expressions as you need for your own project.
Run gradlew checkFileNames if you would like to check only the naming convention.
CheckStyle is used to check the Java code style. Style rules are based on Google Java Style Guide with the following changes:
Run gradlew checkCodeStyle if you would like to check only the code style.
If you would like to exclude some files like 3rd party code, you can add an exclude item in the checkCodeStyle task in the static_analysis.gradle file.
FindBugs scan your code for patterns that may result in bugs. The files to be excluded from the analysis is defined here.
Run gradlew findBugs if you would like to run findbugs only.
PMD is a static code analyzer that can detect common programming flaws. Rules are defined in quality/pmd/pmd-ruleset.xml. Full list of the rules can be found here.
Run gradlew pmdCheck if you would like to run PMD only.
Android Lint is a Android specific static code analysis tool. The full list of checks is here.
Run gradlew lint if you would like to run Lint rules only.
StrictMode is very useful to detect slow operations in UI thread and resource leaks. Specifically, ThreadPolicy will detect disk/network I/O and slow operations in UI thead, whereas VmPolicy will detect resource leaks. For details, see the documents for ThreadPolicy.Builder and VmPolicy.Builder
LeakCanary can help to detect memory leaks. It has a very nice UI to report the leaks and show the whole reference chain so that you can easily locate where to fix the leaks.
The MIT License
Copyright (c) 2017-2017 AndroidQualityEssentials project contributors
https://github.com/BrianSpace/AndroidQualityEssentials/graphs/contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.