本文主要介绍了Android的几种静态代码检查工具。它们分别从不同的角度来帮助我们检查代码的规范性,以便更好的规范我们的开发。最后给出代码检测实践。
1. Lint
Android Studio中提供的Android Lint是一款静态分析工具,通过它可以对Android工程源码进行静态代码分析,它能够检测出应用程序中的潜在漏洞以及其它可能被编译器所忽略的其它代码问题。Android Lint可以在以下几个层面分析代码:correctness正确性,security安全性,performance性能,usability可用性,accessibility可访问性和internationalization国际化。
1.1 Lint 配置
要查看和修改检查的问题严重界别的话,可以使用 File > Settings > Editor > Inspections 菜单来打开检查配置(Inspection Configuration )页,里面有一个支持检查项的清单。
1.2 Lint gradle配置
使用 Android Studio 的话, 你还可以针对特定的构建变量运行 Lint 检查, 或者也可以是来自 build.gradle 文件的所有变量。需要将 lintOptions 属性添加到构建文件的 android 设置中。下面这段代码来自于一个 Gradle 构建文件,它显示了如何将 quiet 选项设置成 true,将 abortOnError 选项设置成 false。
android {
lintOptions {
// set to true to turn off analysis progress reporting by lint
quiet true
// if true, stop the gradle build if errors are found
abortOnError false
// if true, only report errors
ignoreWarnings true
}
...
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
1.3 Lint 运行检查
终端命令行
gradle lint
android studio 工具操作
Analyze > Inspect Code
1.4 Lint 检查结果如下
根据如下的检测结果进行对应的分析和修改
2. Checkstyle
Checkstyle是一款检查java程序代码样式的工具,可以有效的帮助我们检视代码以便更好的遵循代码编写标准,特别适用于小组开发时彼此间的样式规范和统一。Checkstyle提供了高可配置性,以便适用于各种代码规范。
Checkstyle具有很强的配置性.每一个checkstyle配置文件必须包含Checker作为根moduleTreeWalker module用来遍历java文件,并定义一些属性。ThreeWalker module包含了多个子module,用来进行检查规范.
2.1 检查规则
Checkstyle 规则配置遵循java 代码规范以及google代码规范,参考规则如下:
Java官方代码规范
Google Java Style
Checkstyle Configuration
Checkstyle能检测 Javadoc Comments(Javadoc相关)、Naming Conventions(命名惯例)、Headers(文件头检查)、Imports(导入检查)、Size Violations(检查大小)、Whitespace(空白相关)、Modifiers(修饰符相关)、Blocks(代码块)、Class Design(类设计)、Duplicates(重复)等等,更多规则见具体checksyle规则配置。
CheckStyle 规则配置例如:
<module name="Checker">
<module name="JavadocPackage"/>
<module name="TreeWalker">
<module name="AvoidStarImport"/>
<module name="ConstantName"/>
<module name="EmptyBlock"/>
</module>
</module>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
2.2 插件安装
插件安装后,需要重新启动
2.3 使用
checkstyle gradle配置使用
def configDir = "${project.rootDir}/config/quality"
def reportsDir = "${project.buildDir}/reports"
task checkstyle(type: Checkstyle) {
ignoreFailures = true
configFile file("$configDir/checkstyle/checkstyle.xml")
configProperties.checkstyleSuppressionsPath = file("$configDir/checkstyle/suppressions.xml").absolutePath
source 'src'
include '**/*.java'
exclude '**/gen/**'
classpath = files()
reports {
xml.enabled = true
html.enabled = true
}
doLast {
ant.xslt(in: reports.xml.destination,
style: new File("$configDir/checkstyle/checkstyle-simple.xsl"),
out: new File("$configDir", 'checkstyle.html'))
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
终端命令行执行 gradle checkstyle
2.4 更多checkstyle相关链接:
【Checkstyle介绍】http://blog.csdn.net/gtuu0123/article/details/6403994
【一个完整的checkstyle规范】http://wang-jia-sina-com.iteye.com/blog/1887600
【Android代码规范利器: Checkstyle】https://zhuanlan.zhihu.com/p/25004066
【android studio 使用checkstyle全攻略】http://www.codexiu.cn/android/blog/6309/
3. Findbugs
Findbugs是一个静态分析工具,它检查类或者JAR 文件,将字节码与一组缺陷模式进行对比以发现可能的问题。Findbugs自带检测器,其中有60余种Bad practice,80余种Correctness,1种 Internationalization,12种Malicious code vulnerability,27种Multithreaded correctness,23种Performance,43种Dodgy。我们还可以自己配置检查规则(做哪些检查,不做哪些检查),也可以自己来实现独有的校验规则(用户自定义特定的bug模式需要继承它的接口,编写自己的校验类,属于高级技巧)。
Findbugs 也提供了 Android Studio 的插件支持,值得注意的是 Findbugs 分析的是 Java 字节码,所以在启用 Findbugs 之前要保证你的工程是编译过的,在 FIndbugs 扫描之后,如果发现问题,会在对应的代码出给出提示。
3.1 插件安装
类似于checksyle,在Android studio Setting –>plugins–>搜索findbugs。
3.2 使用
3. PMD代码审查
这个工具比较有趣:其实 PMD 真正的名字并不是 PMD 。 在其官方网站上你会发现两个非常有趣的名字:
Pretty Much Done
Project Meets Deadline
事实上 PMD 是一个非常强大的工具,它的作用类似 Findbugs,但是它的检测扫描是基于源码的,而且 PMD 不仅能检测 Java 语言,还能检测其他语言。PMD 的目标和 Findbugs非常的相似,都是通过定义的规则静态分析代码中可能出现的错误,为什么要同时使用 PMD 和 Findbugs呢?由于 Findbugs 和 PMD 的扫描方式不一样,PMD 能发现的一些 Findbugs 发现不了的问题,反之亦然。
PMD附带了许多可以直接使用的规则,利用这些规则可以找出Java源程序的许多问题,例如:
- 潜在的bug:空的try/catch/finally/switch语句
- 未使用的代码:未使用的局部变量、参数、私有方法等
- 可选的代码:String/StringBuffer的滥用
- 复杂的表达式:不必须的if语句、可以使用while循环完成的for循环
- 重复的代码:拷贝/粘贴代码意味着拷贝/粘贴bugs
- 循环体创建新对象:尽量不要再for或while循环体内实例化一个新对象
- 资源关闭:Connect,Result,Statement等使用之后确保关闭掉
此外,用户还可以自己定义规则,检查Java代码是否符合某些特定的编码规范。例如,你可以编写一个规则,要求PMD找出所有创建Thread和Socket对象的操作。
3.1插件安装
类似于checksyle,在Android studio Setting –>plugins–>搜索PMD。
3.2使用
3.3检测结果
4. 代码检测实践
4.1 检测工具的gradle配置
lint checkstyle pmd findbugs的gradle配置,统一写在quality.gradle 文件中,便于管理,配置如下:
apply plugin: 'checkstyle'
apply plugin: 'findbugs'
apply plugin: 'pmd'
// Add checkstyle, findbugs, pmd and lint to the check task.
check.dependsOn 'checkstyle', 'findbugs', 'pmd', 'lint'
def configDir = "${project.rootDir}/config/quality"
def reportsDir = "${project.buildDir}/reports"
task checkstyle(type: Checkstyle) {
ignoreFailures = true
configFile file("$configDir/checkstyle/checkstyle.xml")
configProperties.checkstyleSuppressionsPath = file("$configDir/checkstyle/suppressions.xml").absolutePath
source 'src'
include '**/*.java'
exclude '**/gen/**'
classpath = files()
reports {
xml.enabled = true
html.enabled = true
}
doLast {
ant.xslt(in: reports.xml.destination,
style: new File("$configDir/checkstyle/checkstyle-simple.xsl"),
out: new File("$configDir", 'checkstyle.html'))
}
}
task findbugs(type: FindBugs, dependsOn: "assembleDebug") {
ignoreFailures = true
effort = "max"
reportLevel = "high"
excludeFilter = new File("$configDir/findbugs/findbugs-filter.xml")
classes = files("${project.rootDir}/app/build/intermediates/classes")
source 'src'
include '**/*.java'
exclude '**/gen/**'
classpath = files()
reports {
xml.enabled true
html.enabled = false
xml.withMessages true
}
doLast {
ant.xslt(in: reports.xml.destination,
style: new File("$configDir/findbugs/fancy-hist.xsl"),
out: new File("$configDir", 'findbugs.html'))
}
}
task pmd(type: Pmd) {
ignoreFailures = true
ruleSetFiles = files("$configDir/pmd/pmd-ruleset.xml")
ruleSets = []
source 'src'
include '**/*.java'
exclude '**/gen/**'
classpath = files()
reports {
xml.enabled = true
html.enabled = false
}
doLast {
ant.xslt(in: reports.xml.destination,
style: new File("$configDir/pmd/pmd-report-per-class.xslt"),
out: new File("$configDir", 'pmd.html'))
}
}
android {
lintOptions {
abortOnError true
xmlReport true
htmlReport false
lintConfig file("$configDir/lint/lint.xml")
htmlOutput file("$reportsDir/lint/lint-result.html")
xmlOutput file("$reportsDir/lint/lint-result.xml")
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
在app模块得gardle配置中,引用该配置:
apply from: '../config/quality.gradle'
- 1
4.2检测工具配置规则和报告样式
- checkstyle
checkstyle.xml 代码检测规则配置文件
checkstyle_simple.xml 代码检测报告样式文件
suppressions.xml 检测排除文件配置 - findbugs
findbugs-filter.xml 检测排除文件配置
fancy-hist.xsl 检测报告样式文件 - lint
lint.xml 检测规则 - pmd
pmd-ruleset.xml 检测规则
pmd-report-per-class.xslt 报告样式
4.3 Jenkins 配置和运行
Gradle 提供的方法,我们可以把四个工具的执行任务添加为 “check” task 的依赖:
check.dependsOn 'checkstyle', 'findbugs', 'pmd', 'lint'
- 1
现在,只要我们只想 “check” 这个 task ,Checkstyle、Windbags、PMD 和 Android Lint 都会自动执行。在 commit/push/merge request 之前 执行一下 check 任务,对我们代码质量的提高将是一种非常棒的方式。执行这个任务你可以在命令行中执行:gradlew check。Jenkins 中配置运行如下:
4.2 检测结果及分析
构建结果趋势图,正常情况下应该是逐渐收敛,表明代码越来越规范,越来越健壮。
点击左边任何一项可以查看详细得分析结果,分析结果分类别展示,可以按照包、文件、作者、错误类别、错误类型、警告、详细、新错误来进行分类查看分析。
5.修改不规范代码,使用小技巧
5.1 快捷键设置
快捷键可以在Settings -> Keymap 中查看和修改
5.2 Java和布局文件中的中文字符提取到资源文件中
查找中文字符串,以便提取到资源文件string.xml中,便于管理和国际化
Ctrl+ H 打开文件搜索,输入正则表达式* “[\u4e00-\u9fa5]{1,}”*,选择正则表达式搜索
layout 文件中string字符串,利用快捷键提取到资源文件中
聚焦到字符串,点击该行前面的灯泡,选择Extract Android String… 或者 快捷键 Alt +enter
java文件中 提取string 字符串
快捷键 Alt +enter
5.3 移除无用的资源
移除无用的资源 Refactor–>Remove Unused Resources…
查找无用资源 Analyze–>Run Inspection By Name
快捷键 Ctlr+Alt+Shift+i开源工具
We open source a tool that removes all the unused resources in your android project based on the lint output. It can be found here: https://github.com/KeepSafe/android-resource-remover
5.4 查找和替换
Android Studio打开工程,选中项目,右键弹出选择框
1. 查找
选择“Find in Path..” 或者快捷键 Ctrl+G
2. 替换
选择“Replace in Path..” 或者快捷键 Alt+F
6 参考链接
http://www.cnblogs.com/H-BolinBlog/p/5971826.html
https://stackoverflow.com/questions/6373482/remove-all-unused-resources-from-an-android-project/31669368#31669368
https://zhuanlan.zhihu.com/p/25579247
https://zhuanlan.zhihu.com/p/25923665