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寫入到文件中。

相關文章
相關標籤/搜索