在使用Gradle來打包Android應用以前,Android自動化打包一般會選擇使用ant,ant是一種一步一步來執行任務的工具,一般打包一個apk要通過一個複雜的過程,ant工具經過一步一步完成這些過程來生成一個apk。若是要實現一個複雜一點的打包過程,它的xml配置文件的長度也是足以讓你崩潰的。Gradle的出現讓打包過程變得十分輕鬆,並且配置起來也是簡單易懂。之前須要寫好幾天的配置文件如今只要簡單的幾步就能完成,配合Android Studio更加駕輕就熟。android
一個完整的打包流程以下: app
若是你用Android Studio生成一個項目的話,在app模塊中你會看到一個build.gradle文件,這個文件就是配置這個模塊的地方,大體文件結構以下:ide
apply plugin: 'com.android.application' android { compileSdkVersion 23 buildToolsVersion "23.0.2" defaultConfig { minSdkVersion 8 targetSdkVersion 23 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:19.0.1' }
這裏就不一行行地解釋了,關於Gradle的語法能夠自行Google。工具
這裏主要有兩個小技巧:gradle
// 方法1 (簽名配置方法能夠Google) android { buildTypes { debug {signingConfig signingConfigs.myConfig} release {signingConfig signingConfigs.myConfig} } }
// 方法2 android { buildTypes { debug {packageNameSuffix ".debug"} } }
android { buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' def today = new Date() if (variant.buildType.getName().equals("release")) { println "Change output apk name" variant.outputs.each { output -> output.outputFile = new File( output.outputFile.parent, output.outputFile.name.replace(".apk", "-" + defaultConfig.versionName + "-" + today.format('yyyyMMdd') + ".apk")) } } } } }
Gradle的Android插件中有個BuildVariants的概念,其實簡單來講其實就是buildTypes+productFlavors,buildType前面咱們看到過了,主要就是debug和release的分別。而productFlavors就是咱們用來打包不一樣版本app的主要方式。從字面意思來翻譯指的就是不一樣的「產品特色」。ui
Android Studio會自動根據build.gradle 生成對應的BuildVariants。好比如下代碼:google
android { productFlavors { free {} paid {} } }
會生成如下的BuildVariants:spa
productFlavors能夠是多維的,聽起來好像很難理解,這裏舉個栗子,有以下代碼:插件
android { flavorDimensions("isfree", "channel") productFlavors { free {dimension "isfree"} paid {dimension "isfree"} googleplay {dimension "channel"} wandoujia {dimension "channel"} } }
可以生成以下的BuildVariants:翻譯
這裏咱們就能夠看到,咱們有兩個維度,一個是是否免費,另外一個是渠道,咱們可以生成2*2=4種Flavor,而且每一個Flavor都有debug和release,總共就有8種不一樣的APK。因此理論上來講經過組合Flavor,咱們能夠作到各類不一樣的分類。
接下來咱們來看看productFlavors能作什麼? ### 定義渠道
在國外通常來講開發者不太須要去管渠道的問題,他們的App只須要發往GooglePlay就能夠了,可是在中國,咱們有衆多的APK分發平臺,咱們的APK須要發往各類地方,在作APP統計的時候咱們就須要在APK裏寫入一些特徵變量,發送到統計平臺,以區分不一樣的渠道,在過去用ant打包的時代,咱們一般的作法就是用不一樣的渠道名來重複ant任務一遍一遍地打包。
若是用gradle:咱們能夠經過增長一個名爲channel的dimension來給每個渠道一個特殊標示,代碼就是咱們以前看到的。可是你可能會問,我怎麼在統計的時候獲取這個渠道名呢?其實很簡單,Android Studio會爲咱們生成一個名叫BuildConfig的類,這個類有一些關於打包的靜態變量,下面是一個示例:
public final class BuildConfig { public static final boolean DEBUG = Boolean.parseBoolean("true"); public static final String APPLICATION_ID = "me.zheteng.android.example"; public static final String BUILD_TYPE = "debug"; public static final String FLAVOR = "freeGoogleplay"; public static final int VERSION_CODE = 1; public static final String VERSION_NAME = "1.0"; public static final String FLAVOR_isfree = "free"; public static final String FLAVOR_channel = "googleplay"; }
其實不止是渠道,經過這個類咱們還能夠很方便地得到這個APK的各類信息。相信你們一眼就能看出來每一個字段的意思。(咱們甚至還能夠自定義字段)。
若是渠道很是多,你也能夠經過讀配置文件的方式動態生成不一樣的flavors。
有的時候咱們每一個flavor可能不僅是一個渠道名這麼簡單,個人ICON可能給每一個渠道的有所不一樣,個人包名也可能有所不一樣。全部這些,均可以直接在這個flavor中從新定義:
android { productFlavors { googleplay { applicationId "me.zheteng.android.example.googleplay" } } }
若是須要不一樣的源代碼或資源文件,能夠在app/src下新建一個名爲「flavor名」的目錄(這裏就是googleplay)。也就是app/src/googleplay,而後這個目錄下的結構和app/src/main中是同樣的,打包的時候會優先使用當前flavor下的文件。
咱們知道Provider的authority是系統中全局惟一的,有時候咱們要爲不一樣的flavor將authority改爲不一樣的,經過gradle你能夠這樣實現:
<provider android:exported="true" android:name="com.path.to.my.Provider" android:authorities="${applicationId}.provider"/>
你問我Java代碼中怎麼獲取?難道你忘了BuildConfig了嘛?
有些SDK會把配置在Manifest文件中的meta信息裏,而不一樣的flavor這個信息不同,這是咱們能夠經過Manifest 佔位符來實現:
<meta-data android:value="${UMENG_APPKEY}" android:name="UMENG_APPKEY"/>
android { productFlavors { googleplay { applicationId "me.zheteng.android.example.googleplay" manifestPlaceholders = [UMENG_APPKEY: "個人友盟KEY"] } } }
Gradle的靈活程度超乎想象,若是基本功能沒法知足你,你還能夠經過本身編寫Groovy插件或者task來實現無窮的可能性,歡迎將你的思路分享出來~