android category 自定义,Android 自定义Lint实践总结

本文档介绍了如何在Android Studio中配置和使用Lint工具进行静态代码分析,以提升代码质量。通过调整LintOptions,可以忽略特定错误,如'MissingTranslation',并自定义错误级别。同时,可以通过创建自定义Detector实现对ToastUtils的错误检查,提供错误修复建议。此外,还讲解了如何通过lint.xml文件进一步定制检查规则,并展示了如何构建和应用自定义的lint.jar包。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

自定义Lint

Android Lint 是由 Android SDK 提供的一种静态代码检测工具,用于检测 Android 项目的代码质量,帮你查出可能发生的bug以及可以优化的代码

此文档只针对

AS 3.0+

Gradle 3.3+

Android Plugin Version 3.0.1+

LintOptions配置

如果将 abortOnError 设置为true,自定义Lint很容易出现编译失败,此时检查message窗口将不必要的检查进行忽略禁用十分必要,例如 disable 'MissingTranslation' 此配置将忽略没有对strings.xml进行翻译报的错误。其他配置项查看下面各注释👇

各个配置含义

android {

lintOptions {

// 设置为 true时lint将不报告分析的进度

quiet true

// 如果为 true,则当lint发现错误时停止 gradle构建

abortOnError false

// 如果为 true,则只报告错误

ignoreWarnings true

// 如果为 true,则当有错误时会显示文件的全路径或绝对路径 (默认情况下为true)

//absolutePaths true

// 如果为 true,则检查所有的问题,包括默认不检查问题

checkAllWarnings true

// 如果为 true,则将所有警告视为错误

warningsAsErrors true

// 不检查给定的问题id

disable 'TypographyFractions','TypographyQuotes'

// 检查给定的问题 id

enable 'RtlHardcoded','RtlCompat', 'RtlEnabled'

// * 仅 * 检查给定的问题 id

check 'NewApi', 'InlinedApi'

// 如果为true,则在错误报告的输出中不包括源代码行

noLines true

// 如果为 true,则对一个错误的问题显示它所在的所有地方,而不会截短列表,等等。

showAll true

// 重置 lint 配置(使用默认的严重性等设置)。

lintConfig file("default-lint.xml")

// 如果为 true,生成一个问题的纯文本报告(默认为false)

textReport true

// 配置写入输出结果的位置;它可以是一个文件或 “stdout”(标准输出)

textOutput 'stdout'

// 如果为真,会生成一个XML报告,以给Jenkins之类的使用

xmlReport false

// 用于写入报告的文件(如果不指定,默认为lint-results.xml)

xmlOutput file("lint-report.xml")

// 如果为真,会生成一个HTML报告(包括问题的解释,存在此问题的源码,等等)

htmlReport true

// 写入报告的路径,它是可选的(默认为构建目录下的 lint-results.html )

htmlOutput file("lint-report.html")

// 设置为 true, 将使所有release 构建都以issus的严重性级别为fatal(severity=false)的设置来运行lint

// 并且,如果发现了致命(fatal)的问题,将会中止构建(由上面提到的 abortOnError 控制)

checkReleaseBuilds true

// 设置给定问题的严重级别(severity)为fatal (这意味着他们将会

// 在release构建的期间检查 (即使 lint 要检查的问题没有包含在代码中)

fatal 'NewApi', 'InlineApi'

// 设置给定问题的严重级别为error

error 'Wakelock', 'TextViewEdits'

// 设置给定问题的严重级别为warning

warning 'ResourceAsColor'

// 设置给定问题的严重级别(severity)为ignore (和不检查这个问题一样)

ignore 'TypographyQuotes'

}

}

此部分内容粘贴自简书LintOptions

此外,还可以通过 lint.xml 文件进行lint规则的配置,如果项目工程中没有此文件自行创建在项目module根目录下即可,具体配置参考:

自定义Lint方案

针对不同的自定义lint方案,其中LinkedIn方案可行性最高,将lint.jar放入AAR包中,项目依赖AAR从而进行自定义lint开发,其中lint.jar只对当前项目工程有效。

LinkedIn提供的解决方案原文

项目详细配置

创建java工程,配置Gradle

提供lint.jar,自定义lint规则在此工程中进行

apply plugin: 'java-library'

def lintVersion = "26.0.0-beta5"

dependencies {

compile fileTree(dir: 'libs', include: ['*.jar'])

compileOnly "com.android.tools.lint:lint-api:$lintVersion"

compileOnly "com.android.tools.lint:lint-checks:$lintVersion"

testCompile "junit:junit:4.12"

testCompile "com.android.tools.lint:lint:$lintVersion"

}

jar {

manifest {

attributes("Lint-Registry-v2":"com.appchina.android.lint.core.AppChinaIssueRegistry")

}

}

创建AAR,配置Gradle

apply plugin: 'com.android.library'

...

dependencies {

lintChecks project('lintCoreLibrary') //lintCoreLibrary为上面的java工程名

}

...

此处 lint 还不会生效,需要将 aar 包引用到主项目,两种方式:

1.手动编译出 .aar 集成至主项目,即放至 libs 目录并进行 aar 依赖

2.还上传至 JCenter,进行远程依赖,更新更为方便

创建Detector

下面是系统ToastUtilsDetector的源码

public class ToastUtilsDetector extends Detector implements Detector.UastScanner {

private static final Class extends Detector> DETECTOR_CLASS = ToastUtilsDetector.class;

private static final EnumSet DETECTOR_SCOPE = Scope.JAVA_FILE_SCOPE;

private static final Implementation IMPLEMENTATION = new Implementation(

DETECTOR_CLASS,

DETECTOR_SCOPE

);

private static final String ISSUE_ID = "ToastUseError";

private static final String ISSUE_DESCRIPTION = "You should use our{ToastUtils}";

private static final String ISSUE_EXPLANATION = "You should NOT use android.widget.Toast directly. Instead you should use ToastUtils we offered.";

private static final Category ISSUE_CATEGORY = Category.CORRECTNESS;

private static final int ISSUE_PRIORITY = 9;

private static final Severity ISSUE_SEVERITY = Severity.ERROR;

private static final String CHECK_PACKAGE = "android.widget.Toast";

public static final Issue ISSUE = Issue.create(

ISSUE_ID,

ISSUE_DESCRIPTION,

ISSUE_EXPLANATION,

ISSUE_CATEGORY,

ISSUE_PRIORITY,

ISSUE_SEVERITY,

IMPLEMENTATION

);

@Override

public List getApplicableMethodNames() {

return Arrays.asList("makeText", "show");

}

@Override

public void visitMethod(@NonNull JavaContext context, @NonNull UCallExpression node, @NonNull PsiMethod method) {

if (!context.getEvaluator().isMemberInClass(method, CHECK_PACKAGE)) {

return;

}

List args = node.getValueArguments();

UExpression duration = null;

if (args.size() == 3) {

duration = args.get(2);

}

LintFix fix = null;

if (duration != null) {

String replace;

if ("Toast.LENGTH_LONG".equals(duration.toString())) {

replace = "ToastUtils.showLong(" + args.get(0).toString() + ", " + args.get(1).toString() + ");";

} else {

replace = "ToastUtils.showShort(" + args.get(0).toString() + ", " + args.get(1).toString() + ");";

}

fix = fix().name("Replace with ToastUtils")

.replace()

.with(replace)

.build();

}

if (fix != null) {

context.report(ISSUE, node, context.getLocation(node), ISSUE_DESCRIPTION, fix);

}

}

}

LintFix 提供快捷修复错误,如上面代码中快捷替换错误代码片段;支持使用正则表达式,具体api可查看LintFix源码,使用比较简单;

如果不需要快捷修复,可以使用JavaContext.report()的其他方法,此时只会进行代码标注(红(Error) / 黄(Waring))提示,Alt+Enter并不会出现快捷修复的提示

自定义Detector需要继承自Detector并实现 Detector.UastScanner 接口,25.2.0及之前版本的Detector.JavaPsiScanner已被弃用,UastScanner相比于JavaPsiScanner以及更老的JavaScanner,主要提供了对Kotlin支持,API更加简单,特点是成对存在(满足条件 -> visitor)此外可以lint-checks-version.jar中的各类型Detector源码可以学习其用法。

UastScanner包含13个回调方法,下面介绍常用的几个:

1.getApplicableUastTypes

此方法返回需要检查的AST节点的类型,类型匹配的UElement将会被createUastHandler(createJavaVisitor)创建的UElementHandler(Visitor)检查。

2.createUastHandler

创建一个UastHandler来检查需要检查的UElement,对应于getApplicableUastTypes

3.getApplicableMethodNames

返回你所需要检查的方法名称列表,或者返回null,相匹配的方法将通过visitMethod方法被检查

4.visitMethod

检查与getApplicableMethodNames相匹配的方法

5.getApplicableConstructorTypes

返回需要检查的构造函数类型列表,类型匹配的方法将通过visitConstructor被检查

6.visitConstructor

检查与getApplicableConstructorTypes相匹配的构造方法

7.getApplicableReferenceNames

返回需要检查的引用路径名,匹配的引用将通过visitReference被检查

8.visitReference

检查与getApplicableReferenceNames匹配的引用

9.appliesToResourceRefs

返回需要检查的资源引用,匹配的引用将通过visitResourceReference被检查

10.visitResourceReference

检查与appliesToResourceRefs匹配的资源引用

11.applicableSuperClasses

返回需要检查的父类名列表,此处需要类的全路径名

11.visitClass

检查applicableSuperClasses返回的类

ISSUE

ISSUE在每个Detector中定义,lint检查到相关项将ISSUE报告出来,示例:

public static final Issue ISSUE = Issue.create(

"ListView",

"AppChinaLint:Replace 'ListView' with 'RecyclerView'",

"RecyclerView is better than ListView",

Category.CORRECTNESS, 6, Severity.WARNING,

new Implementation(ListViewDetector.class, Scope.JAVA_FILE_SCOPE));

在此处可自定义错误描述、安全级别(WARNING、ERROR等)

Category

Category表示lint结果在IDE中的分类,系统已有类别:

Lint

Correctness (incl. Messages)

Security

Performance

Usability (incl. Icons, Typography)

Accessibility

Internationalization

Bi-directional text

此外还可以自定义Category,示例:

public class MTCategory {

public static final Category NAMING_CONVENTION = Category.create("命名规范", 101);

}

IssueRegistry

提供需要被检测的Issue列表,示例:

@Override

public synchronized List getIssues() {

return Arrays.asList(

LogDetector.ISSUE,

ListViewDetector.ISSUE,

HashMapForJDK7Detector.ISSUE,

ToastUtilsDetector.ISSUE,

SampleCodeDetector.ISSUE,

FindViewDetector.ISSUE,

BaseActivityDetector.ISSUE,

BaseFragmentDetector.ISSUE

);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值