书接上回《Android模块化设计之组件开发规范》,组件开发的规范已经定义好了,但目前还有个问题,就是如何统计当前项目中所使用到我们封装的组件库里的组件?
因为公司有十多个项目在并行开发,每个项目使用了那些组件,又是什么版本?如果不能收集这些信息,就很难推动组件的建设工作。但是让每个项目的负责人定时上报各个组件的版本不仅low,而且效率低。
如果能让Gradle脚本帮我们处理这重复机械性的工作,那岂不美哉?
于是它来了:
import groovy.json.JsonBuilder
//自定义上报间隔时间 当前为每3天上报一次
def reportTimeInterval = 3 * 24 * 60 * 60 * 1000
def reportInfo = new ReportInfo()
def isNeedReport = false
// 遍历所有的子模块
subprojects {
project.afterEvaluate {
// 只收集Application下的依赖即可
def isApp = project.plugins.hasPlugin("com.android.application")
if (isApp) {
isNeedReport = checkReportStatus(reportTimeInterval)
if (isNeedReport) {
println("---> 开始检测依赖组件...")
reportInfo.projectName = "${project.rootProject.name}"
reportInfo.reportTime = new Date().time
// 获取配置信息
project.configurations.all {
// 遍历所有依赖,包括间接依赖
resolutionStrategy.eachDependency { details ->
analysisDeps(details, reportInfo)
}
}
} else {
println("---> 小于设定的间隔时间,无需上报依赖,检测结束")
}
}
}
}
// 分析依赖内容并生成上报对象
def analysisDeps(details, reporter) {
def group = details.requested.group
def name = details.requested.name
def version = details.requested.version
def library = "$group:$name"
// 这里可以过滤想要上报的组件信息,过滤掉不关心的内容
// 可以自行定义多个过滤规则
if (group == "com.company.android") {
if (reporter.libraries.containsKey(library)) {
def libraryInfo = reporter.libraries.get(library)
libraryInfo.versions.add("$version")
} else {
def libraryInfo = new ReportLibraryInfo()
libraryInfo.group = group
libraryInfo.name = name
libraryInfo.versions.add("$version")
reporter.libraries.put(library, libraryInfo)
}
}
}
// 判断当前是否需要更新
def checkReportStatus(interval) {
Properties pro = new Properties()
// 从临时文件depsCache.properties 里读取上次上报的时间
def proFile = project.rootProject.file('.depsCache.properties')
//如果文件不存在
if (!proFile.exists()) {
proFile.createNewFile()
updateReportTime(pro, proFile)
return true
}
InputStream inputStream = proFile.newDataInputStream()
pro.load(inputStream)
def preRecordTime = pro.getProperty("preRecordTime")
if (preRecordTime == null) {
updateReportTime(pro, proFile)
return true
}
def preRecordTimeLong = preRecordTime.toLong()
println("---> 上次上报时间 ${new Date(preRecordTimeLong).format("yyyy-MM-dd HH:mm", TimeZone.getTimeZone("GMT+08:00"))}")
def currentTime = new Date().time
def temp = currentTime - preRecordTimeLong
if (temp > interval) {
updateReportTime(pro, proFile)
return true
} else {
println("---> 小于上报间隔,无需检测依赖")
return false
}
}
//更新上次上报时间
def updateReportTime(properties, file) {
def currentTime = new Date().time
properties['preRecordTime'] = "$currentTime".toString()
properties.store(file.newWriter(), "\n This file is automatically generated. Do not manually modify it \n")
}
// gradle任务执行完毕后
gradle.buildFinished {
if (isNeedReport) {
reportDeps("${new JsonBuilder(reportInfo).toPrettyString()}")
}
}
// 通过网络请求把使用到的组件信息上报到自己实现的服务器端,做持久化处理,完成对当前项目组件使用情况的收集
def reportDeps(content) {
println("$content")
def post = new URL("http://localhost:3000/report").openConnection();
post.setRequestMethod("POST")
post.setDoOutput(true)
post.setRequestProperty("Content-Type", "application/json")
post.getOutputStream().write(content.getBytes("UTF-8"));
def postRC = post.getResponseCode();
if (postRC == 200) {
println(post.getInputStream().getText());
}
}
class ReportInfo {
String projectName
long reportTime
Map<String, ReportLibraryInfo> libraries = new HashMap<>()
}
class ReportLibraryInfo {
String group
String name
Set<String> versions = new HashSet()
}
Gradle脚本写好了,我们给它命名为depsReport.gradle吧,然后在我们项目的根目录下引入该脚本(建议把脚本托管到服务器,然后使用远程依赖):
apply from: "depsReport.gradle"
该脚本会在运行任何Gradle命令时触发,并生成一个用于记录上报时间的文件depsCache.properties,可以对该文件进行忽略,避免提交到Git仓库。
只需要每个项目都接入这个脚本,就是统计到当前所有项目的组件库使用情况,终于不用每个项目负责人每周手动上报了,果然,"懒惰"才是第一生产力呀~