如何使用Gradle脚本对依赖库进行统计上报?

1,784 阅读2分钟

书接上回《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仓库。

只需要每个项目都接入这个脚本,就是统计到当前所有项目的组件库使用情况,终于不用每个项目负责人每周手动上报了,果然,"懒惰"才是第一生产力呀~

点赞.jpeg