0%

Gradle获取依赖aar包差异

在发版之前,我们需要关注的一个指标是包体积,作为一个模块化的项目,如果各模块是以aar的方式依赖到主项目(壳儿)中,那么你可以使用如下的方式来分析两个版本之间的aar文件差异,并输出结果。

效果图

使用方式

Root/build.gralde

1
2
3
4
5
6
7
8
buildscript {
repositories {
maven { url "https://jitpack.io" }
}
dependencies {
classpath 'com.github.JuneLeo:dependencies-diff:1.1.2'
}
}

Project/build.gradle

版本一(分支1)

1
2
3
4
5
//输出到根目录 dependencies.csv
task dps(type: com.card.script.get.DependenciesGetTask){
exclude = ["support"]
classpath = 'runtime' // compile,runtime,all
}

版本二(分支2)

1
2
3
4
5
6
7
8
9
10
11
12
//输出到根目录dependencies.csv
task dps(type: com.card.script.get.DependenciesGetTask){
exclude = ["support"]
classpath = 'runtime' // compile,runtime,all
}
// 比较两个dependencies.csv并输出html
task dps2(type:com.card.script.diff.DependenciesDiffTask){
firstPath='/Users/juneleo/amap/amap_android/dependencies.csv'
secondPath='/Users/juneleo/amap/amap_android_backup/amap_android/dependencies.csv'
outType='html' //html,console
excludeModuleFile =['/arm64-v8a/'] // 过滤文件
}

原理

收集项目依赖

1.获取项目依赖的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 获取项目编译时的依赖
Configuration compileClassPathConfiguration =
getProject().getConfigurations().getByName(variantName + "CompileClasspath")

// 获取项目运行时的依赖
Configuration runtimeClassPathConfiguration =
getProject().getConfigurations().getByName(variantName + "RuntimeClasspath")

// 获取所有的不重复的依赖 集合
Set<ResolvedComponentResult> resolvedComponentResults =
compileClassPathConfiguration.getIncoming().getResolutionResult().getAllComponents()

// 获取全部依赖,有重复 集合
dependenciesConfiguration.getIncoming().getResolutionResult().getAllDependencies()

// 非所有依赖,只有task 所在build.gradle 中的依赖的集合(一级依赖)
dependenciesConfiguration.getIncoming().getResolutionResult().getRoot().getDependencies()

2.获取aar的本地路径

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
// 构建请求参数
Action<AttributeContainer> attributes = new Action<AttributeContainer>() {
@Override
void execute(AttributeContainer container) {
//key : AndroidArtifacts.MODULE_PATH,AndroidArtifacts.ARTIFACT_TYPE
//AndroidArtifacts中type类型 aar,android-classes等,会帮我们过滤
// 配置有疑问 参考 VariantScopeImpl 中
//container.attribute(ARTIFACT_TYPE, "android-classes");
}
}


ArtifactCollection compileArtifactCollection =
compileClassPathConfiguration.getIncoming()
.artifactView(new Action<org.gradle.api.artifacts.ArtifactView.ViewConfiguration>() {
@Override
void execute(org.gradle.api.artifacts.ArtifactView.ViewConfiguration viewConfiguration) {
viewConfiguration.lenient(true)
viewConfiguration.attributes(attributes)
}
}).getArtifacts();

ArtifactCollection runtimeArtifactCollection =
runtimeClassPathConfiguration.getIncoming()
.artifactView(new Action<org.gradle.api.artifacts.ArtifactView.ViewConfiguration>() {
@Override
void execute(org.gradle.api.artifacts.ArtifactView.ViewConfiguration viewConfiguration) {
viewConfiguration.lenient(true)
viewConfiguration.attributes(attributes)
}
}).getArtifacts();

// 获取路径集合
Set<ResolvedArtifactResult> resolvedArtifactResults =
compileArtifactCollection.getArtifacts()

比较依赖

1.解压

1
2
3
4
5
6
7
8
9
10
11
12
def copy(String fromPath, String outPath) {
getProject().copy {
from(getProject().zipTree(fromPath))
into(outPath)
// 判断解压路径outPath中是否有jar包,有的话继续解压
File [] outPathFiles = getProject().file(i).listFiles()
for(File child : outPathFiles) {
if(child.getName().contains('.jar')) {
copy(childFile.getAbsolutePath(), childFile.getAbsolutePath() + "_dir")
}
}
}

2.比较

  • 遍历 原版本的解压文件

    • 原版路径 : xxxxxx-build/xxxxxx-build:10.1.80.873/A.class
    • 比较路径 : xxxxxx-build/xxxxxx-build:10.2.5.30/A.class
    • 使用路径module名替换的方式来比较,这样可以获取到 增大,新增,减小,相等的文件,获取不到删除的文件
  • 遍历 比较版本的解压文件
    同上,使用此种方式获取被删除的文件

3.输出

输出方式:html,console