Android端生成META-INF信息文件的Gradle插件 RapidMetaInfPlugin

来源博客:Wang Jie's Blog
本文连接:http://blog.wangjiegulu.com/2018/02/05/Android%E7%AB%AF%E7%94%9F%E6%88%90META-INF%E4%BF%A1%E6%81%AF%E6%96%87%E4%BB%B6%E7%9A%84Gradle%E6%8F%92%E4%BB%B6%20RapidMetaInfPlugin/
版权声明:本博客全部文章除特别声明外,均采用 CC BY 4.0 CN协议 许可协议。转载请注明出处。
java

Android端生成META-INF信息文件的Gradle插件 RapidMetaInfPlugin

1. 需求背景

最近新遇到了一个需求,想在本身的一些库中写入版本信息,在别人使用了个人库后,我能够经过apk文件检测出依赖了个人哪一个版本的库。感受这个需求有点多余?那就举个例子吧。react

好比,我编写了一个开源库:RapidORM,并上传到了Maven中心库 ,假设一个我不认识的开发者(暂且称它为X)在编写app,这个app中的代码对我来讲是彻底未知的,可是他经过在build.gradle中添加了以下依赖:android

compile "com.github.wangjiegulu:rapidorm:1.0.0"
compile "com.github.wangjiegulu:rapidorm-api:1.0.0"
apt "com.github.wangjiegulu:rapidorm-compiler:1.0.0"

很明显,X依赖了我写的RapidORM库。而且打包成了Apk文件而后发布。这时我下载了这个apk,而且但愿获得这个apk中依赖的RapidORM版本是多少?这个RapidORM在构建这个aar时的开发环境是怎么样的?反编译可能有但愿能拿到RapidORM具体的版本号,可是aar当时的构建环境就没法得知了。git

这时,我就但愿在我发布RapidORM的Release版本的时候可以在aar中携带好一些自定义的参数,而且这些信息会在依赖了这个库的开发者X构建apk的时候跟随保存到apk文件中。github

比较典型的一个例子当你依赖了RxJava这个库,咱们构建apk完成以后,会发如今咱们的apk文件中的META-INF文件夹下面会有一个rxjava.properties文件,打开这个文件就会发现以下内容:api

Manifest-Version=1.0
Implementation-Title=io.reactivex.rxjava2#rxjava;2.1.2
Implementation-Version=2.1.2
Built-Status=integration
Built-By=travis
Built-OS=Linux
Build-Date=2017-07-23_08:21:58
Gradle-Version=2.14
Module-Owner=benjchristensen@netflix.com
Module-Email=benjchristensen@netflix.com
Module-Source=
Module-Origin=https://github.com/ReactiveX/RxJava.git
Change=e4fbe4c
Branch=e4fbe4cfcb3c240d14a42a586eecbbd74cb379d2
Build-Host=testing-gce-361876de-b66f-4569-b841-e037b0fee9af
Build-Job=LOCAL
Build-Number=LOCAL
Build-Id=LOCAL
Created-By=1.7.0_80-b15 (Oracle Corporation)
Build-Java-Version=1.7.0_80
X-Compile-Target-JDK=1.6
X-Compile-Source-JDK=1.6

很显然,这个文件中包含了:RxJava版本号, 构建的CI信息构建时间, Gradle版本, 模块负责人信息, git分支, JDK版本等等。数组

经过这个方式,我能够在任意的apk中拿到它依赖的RxJava的信息。app

固然,你能够经过在build.gradle进行以下配置来过排除这个rxjava.properties文件(可是不建议这么作,这个文件也许能在你遇到问题时给你帮助):maven

android {
    ...
    packagingOptions {
        exclude 'META-INF/rxjava.properties'
    }
}

2. RapidMetaInfPlugin Gradle 插件

RapidMetaInfPlugin: https://github.com/wangjiegulu/RapidMetaInfPlugingradle

所以,写了 RapidMetaInfPlugin 这个 Gradle 插件。

此次先说说怎么使用这个插件,之后抽时间再写一篇 Gradle 插件编写教程。以前也写过一个Gradle插件(详情见Android Gradle 插件 DiscardFilePlugin(清空类和方法))也挺实用的。

2.1 最终效果

经过这个插件,咱们能够在apk或者aarapp依赖后合并到apk)中写入任意信息。

以上在这个apkMETA-INF中生成了一个名为DAL_REQUEST.properties的文件,内容中包含了dal_request这个库的名字、版本号和url。

2.2 如何使用

在你的buildscriptdependencies中添加classpath依赖(点击这里获取最新版本):

buildscript {
    repositories {
        jcenter()
        google()
    }
    dependencies {
        // ...
        classpath ('com.github.wangjiegulu:rapidmetainf:x.x.x'){
            exclude group: 'com.android.tools.build', module: 'gradle'
        }
    }
}

而后在你的apk或者aar的build.gradle文件的顶部写入如下代码来使用插件:

apply plugin: 'com.github.wangjiegulu.plg.rapidmetainf'

而后经过以下方式填写你须要写进META-INF目录中的文件信息:

rapidmetainf {
    metaInfName 'DAL_REQUEST.properties'
    metaInfProperties "archiveName=$dbarchiveName",
            "archiveVersion=$dbarchiveVersion",
            "archiveUrl=$dbarchiveUrl"
}

如上,metaInfName表示在META-INF目录中生成的文件名称(文件名任意取,可是不能以"."开头),metaInfProperties表示要写入文件的数据,这个变量为数组类型,可经过Groovy语法来编写,好比经过$符号来引用ext,经过以下命令参数的方式等等:

rapidmetainf {
    metaInfName 'DAL_REQUEST_DEMO.properties'

    String[] infArray = new String[10]
    // ./gradlew clean build -PcommandKey=commandValue
    infArray[0] = "propertyFromCommand=${getParameter('commandKey')}"
    for(int i = 1; i < infArray.length; i++){
        infArray[i] = "array_item_key_$i=array_item_value_$i"
    }

    metaInfProperties infArray
}

def getParameter(String key) {
    // -D
    String value = System.getProperty(key)
    if (null != value && value.length() > 0) {
        return value
    }
    // -P
    if (hasProperty(key)) {
        return getProperty(key)
    }
    return null
}

以上,CI构建时就可以使用命令./gradlew clean build -PcommandKey=commandValue来把commandValue写入到文件中。

相关文章
相关标签/搜索