來源博客: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
最近新遇到了一個需求,想在本身的一些庫中寫入版本信息,在別人使用了個人庫後,我能夠經過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' } }
RapidMetaInfPlugin: https://github.com/wangjiegulu/RapidMetaInfPlugingradle
所以,寫了 RapidMetaInfPlugin 這個 Gradle 插件。
此次先說說怎麼使用這個插件,之後抽時間再寫一篇 Gradle 插件編寫教程。以前也寫過一個Gradle插件(詳情見Android Gradle 插件 DiscardFilePlugin(清空類和方法))也挺實用的。
經過這個插件,咱們能夠在apk
或者aar
(app
依賴後合併到apk
)中寫入任意信息。
以上在這個apk
的META-INF
中生成了一個名爲DAL_REQUEST.properties
的文件,內容中包含了dal_request
這個庫的名字、版本號和url。
在你的buildscript
的dependencies
中添加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
寫入到文件中。