自定义Lint检测含Gradient的Vector时出现AGP兼容异常排查
问题原因与解决方案
问题原因分析
context.mainProject的误用:AGP 8.1.0 中,在模块分析阶段调用context.getMainProject()会导致上下文混淆。Lint处理库模块时,mainProject指向库本身而非消费它的应用模块,触发内部校验错误——即使没有违规代码也会报错。- 直接文件系统访问资源:当前实现通过遍历文件系统读取Drawable文件,绕过Lint的资源解析机制,依赖固定项目结构,无法处理多模块、构建变体或资源合并场景,易引发不可预期问题。
替代方案:规范的Lint检测实现
修正后的Detector代码
import com.android.tools.lint.detector.api.* import com.android.tools.lint.detector.api.XmlContext import org.w3c.dom.Attr class VectorGradientDetector : ResourceXmlDetector() { companion object { private const val TAG_VECTOR = "vector" private const val TAG_GRADIENT = "gradient" val ISSUE = Issue.create( id = "VectorGradientIssue", briefDescription = "使用android:src加载含渐变的VectorDrawable", explanation = "API 21以下设备使用android:src加载包含<gradient>的VectorDrawable会崩溃,应改用app:srcCompat", category = Category.CORRECTNESS, severity = Severity.FATAL, implementation = Implementation( VectorGradientDetector::class.java, Scope.RESOURCE_FILE_SCOPE ) ) } override fun appliesTo(folderType: ResourceFolderType): Boolean { return folderType == ResourceFolderType.LAYOUT } override fun getApplicableAttributes(): Collection<String>? { return listOf(SdkConstants.ATTR_SRC) } override fun visitAttribute(context: XmlContext, attribute: Attr) { // 仅检测android命名空间的src属性 if (!attribute.namespaceURI.equals(SdkConstants.ANDROID_URI)) { return } // 解析Drawable资源ID val resourceId = context.resourceResolver.resolveResourceId(attribute.value) if (resourceId == 0) { return } // 获取Drawable资源的XML内容 val resourceXml = context.resourceResolver.getXml(resourceId) ?: return // 检查是否为包含gradient的VectorDrawable var isVector = false var hasGradient = false XmlScanner.visitDocument(resourceXml) { node -> when (node.nodeName) { TAG_VECTOR -> isVector = true TAG_GRADIENT -> hasGradient = true } } if (isVector && hasGradient) { context.report( ISSUE, attribute, context.getValueLocation(attribute), "含渐变的VectorDrawable应使用app:srcCompat加载,避免API 21以下设备崩溃" ) } } }
关键改进点
- 使用Lint内置资源解析器:通过
ResourceResolver获取Drawable的XML内容,兼容多模块、构建变体和资源合并逻辑,避免直接文件系统访问的问题。 - 移除
mainProject依赖:仅使用当前模块的资源上下文,避免AGP 8+的跨模块上下文错误。 - 精确XML节点检测:使用Lint的
XmlScanner解析资源内容,替代字符串匹配,减少误判概率。
Gradle配置修正
AGP 8.1.0与Lint版本对齐,需更新规则模块的依赖版本:
apply plugin: 'java-library' apply plugin: 'kotlin' jar { manifest{ attributes 'Lint-Registry-V2': 'com.xyz.rules.IssueRegistry' } } dependencies { implementation "com.android.tools.lint:lint-api:8.1.0" implementation "com.android.tools.lint:lint-checks:8.1.0" }
验证与测试
- 修复后执行
./gradlew app:lint,无论是否存在违规代码,均不会触发异常。 - 确保所有包含
<gradient>标签的VectorDrawable在使用android:src时被正确检测,使用app:srcCompat时无报错。
内容的提问来源于stack exchange,提问作者Veeresh Charantimath
相关产品推荐
相关产品推荐

