github地址 https://github.com/mikaelzero/KotlinJunk
前言
本库参考自 https://github.com/qq549631030/AndroidJunkCode 的实现,主要区别在于本库生成的是kotlin的代码,并且各个资源的名称随机性高,基于Bosster进行开发插件,方便集成
实现的效果
在打包之后会出现大量的垃圾代码,无用代码,来避免某些平台检测代码重复度的时候出现的问题
如何生成垃圾代码
以kotlin为例,通过 kotlinpoet 框架来生成kotlin文件,生成的文件通过IO流保存在项目的某个目录下
drawable的生成只能生成vector,因为vector可以通过代码进行动态调整生成
生成string文件的话,首先要创建 string.xml 文件,然后通过 FileReader 来读取XML文件的节点然后进行数据的插入操作
同理如果是一个Activity,自然要先注册,因此同样是先创建 AndroidManifest 文件,通过 FileReader 来读取XML文件的节点然后进行数据的插入操作
因此生成代码的操作,主要由 kotlinpoet 以及 IO流 来处理
如何将这些代码打包进APK中
Android Studio 按逻辑关系将每个模块的源代码和资源分组为源代码集,在打包阶段,Android Plugin 插件会读取源代码集来判断哪些代码需要打包进入apk,IDE创建项目时会默认设置项目的main/java 为源代码集目录
类似这样的配置
sourceSets {
main {
java {
srcDirs += []
}
kotlin {
srcDirs += ['src/main/kotlin', 'src/main/java']
}
}
test {
java {
srcDirs += []
}
kotlin {
srcDirs += ['src/main/kotlin', 'src/main/java']
}
}
}
如果你想让某个目录的类或者资源能够打包进APK,你需要在sourceSets中进行add的配置,由于我们实现的是一个插件,因此我们需要自己把之前生成的目录,自动添加到 srcDirs 中
val generatedResFolders = variant.project.files(resDir).builtBy(it)
variant.registerGeneratedResFolders(generatedResFolders)
variant.registerJavaGeneratingTask(it, javaDir)
registerGeneratedResFolders 的官网注释为 Adds to the variant new generated resource folders,也就代表着我们可以将自己生成的路径注册进去,registerJavaGeneratingTask也是同理
另外还有清单配置文件的合并问题,一段官方描述如下:
可以看出,如果我们没有设置变体和产品变种,默认为两种源代码集,一个为 src/debug/ ,一个为 src/main/
在BaseVariant的sourceSets中可以获取到对应的两个SourceProvider,通过SourceProvider的 getManifestFile 可以获取到绝对路径,这个路径有可能不存在内容,因此我们可以在不存在的情况下,把我们自己生成的清单文件路径赋值给SourceProvider
variant.sourceSets.forEach { sourceSet ->
if (!sourceSet.manifestFile.exists()) {
android.sourceSets.maybeCreate(sourceSet.name).manifest.srcFile(manifestFile.absolutePath)
return@forEach
}
}
Kotin代码
考虑到生成的是kotlin代码,在registerJavaGeneratingTask有备注支持kotlin生成,但是随着版本更新可能移除,因此需要选择另外一个方式来将kotlin的类打入包中
val kotlinCompileTask = tasks.findByName("compile${variant.name.capitalize()}Kotlin") as? SourceTask
if (kotlinCompileTask != null) {
kotlinCompileTask.dependsOn(it)
val srcSet = variant.project.objects.sourceDirectorySet("kotlin", "kotlin").srcDir(javaDir)
kotlinCompileTask.source(srcSet)
}
总结
- 如何生成代码,主要是kotlinpoet或者javapoet以及IO流来操作文件
- 如何打包入APK,主要是通过sourceSets的动态添加