看完這篇你學到什麼: 熟悉gradle的構建配置 熟悉代碼構建環境的目錄結構,你知道的不僅僅是只有src/main 開發、生成環境等等環境可以任意切換打包 多渠道打包 APK輸出文件配置 需求 一般我們開發的環境分為:debug 和 release,但是你想再分內測1環境、內測2環境等等怎麼辦呢? ...
看完這篇你學到什麼:
- 熟悉gradle的構建配置
- 熟悉代碼構建環境的目錄結構,你知道的不僅僅是只有src/main
- 開發、生成環境等等環境可以任意切換打包
- 多渠道打包
- APK輸出文件配置
需求
一般我們開發的環境分為:debug 和 release,但是你想再分內測1環境、內測2環境等等怎麼辦呢?
這就需要依賴強大的gradle 來配置了。
相關的配置也可以參考谷歌官方文檔。
配置構建類型 buildTypes
您可以在模塊級 build.gradle
文件的 android {}
代碼塊內部創建和配置構建類型。當您創建新模塊時,Android Studio 會自動為您創建調試和發佈這兩種構建類型。儘管調試構建類型不會出現在構建配置文件中,Android Studio 會將其配置為 debuggable true
。這樣,您可以在安全的 Android 設備上調試應用並使用通用調試密鑰庫配置 APK 簽署。
如果您希望添加或更改特定設置,您可以將調試構建類型添加到您的配置中。以下示例為調試構建類型指定了 applicationIdSuffix
,並配置了一個使用調試構建類型中的設置進行初始化的jnidebug
構建類型。
applicationIdSuffix:
欄位表示,在不改變你預設的程式ID(包名)的情況下,為其添加尾碼。比如你的包名是com.rae.app
,但你想區分測試包和正式包的情況,這個時候將applicationIdSuffix
設置為.debug
,那麼你的應用程式對應的包名就變成了com.rae.app.debug
android {
...
defaultConfig {...}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
applicationIdSuffix ".debug"
}
/**
* The 'initWith' property allows you to copy configurations from other build types,
* so you don't have to configure one from the beginning. You can then configure
* just the settings you want to change. The following line initializes
* 'jnidebug' using the debug build type, and changes only the
* applicationIdSuffix and versionNameSuffix settings.
*/
jnidebug {
// This copies the debuggable attribute and debug signing configurations.
initWith debug
applicationIdSuffix ".jnidebug"
jniDebuggable true
}
}
}
構建源集
我們都知道,源代碼是放在src/main
文件夾下的,但是由於配置了不同的構建類型像想要區分不同的源文件怎麼辦呢?這個時候就可以在src
對應你的buildTypes
來建立文件夾了 ,更多參考谷歌源集。
Android Studio 按邏輯關係將每個模塊的源代碼和資源分組為源集。模塊的 main/ 源集包括其所有構建變體共用的代碼和資源。其他源集目錄為可選項,在您配置新的構建變體時,Android Studio 不會自動為您創建這些目錄。不過,創建類似於 main/ 的源集有助於讓 Gradle 只應在構建特定應用版本時使用的文件和資源井然有序:
productFlavor
表示渠道包,可以看下麵的多渠道打包
src/main/
此源集包括所有構建變體共用的代碼和資源。
src/
<buildType>
/
創建此源集可加入特定構建類型專用的代碼和資源。示例:src/jnidebug
src/
<productFlavor>
/
創建此源集可加入特定產品風味專用的代碼和資源。比如百度渠道包:src/baidu
src/
<productFlavorBuildType>
/
創建此源集可加入特定構建變體專用的代碼和資源。
例如,要生成應用的“完全調試”版本,構建系統需要合併來自以下源集的代碼、設置和資源。比如:百度的開發環境包:src/baiduDebug
構建類型依賴配置
很多時候我們會把sdk或者api介面單獨做成一個庫,一般會有生產環境和測試環境之分,但在依賴的時候往往我們會像這樣去引用:compile project(':sdk')
,這樣依賴的環境就是release
,在開發調試的時候測試環境的時候就不行了。我們得換另外一種方式:
<buildType>
Compile project()
這樣會根據不同的構建類型去依賴不同的包,比如我們測試環境的依賴包:debugCompile project(':sdk')
,再比如上面的jnidebug
:jnidebugCompile project(':sdk')
那麼問題來了,我當前的構建類型怎麼對應到其他的module
去呢?比如你的app要依賴sdk module 的debug 環境,那麼你可以這麼做:
configuration
:目標module
的<buildType>
,比如你sdk 中<buildType>
的debug
構建類型
debugCompile project(path: ':sdk', configuration: 'debug')
綜合示例:
1、先看app這邊的build.gradle
配置:
apply plugin: 'com.android.application'
android {
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
applicationIdSuffix '.debug'
minifyEnabled false
}
// 自定義的構建類型,名字隨便取,一定要有意義
raedebug {
initWith debug
applicationIdSuffix '.raedebug'
}
}
}
dependencies {
// 生成環境依賴
releaseCompile project(path: ':sdk', configuration: 'release')
// 測試環境依賴
debugCompile project(path: ':sdk', configuration: 'debug')
// 自定義構建類型依賴
raedebugCompile project(path: ':sdk', configuration: 'uutest')
}
2、sdk module的build.gradle
配置:
apply plugin: 'com.android.library'
android {
buildTypes {
debug {
debuggable true
minifyEnabled false
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
// 註意這裡,跟第一點的 raedebugCompile project的configuration要匹配。
uutest {
initWith debug
}
}
}
多渠道打包 productFlavors
先看看build.gradle
配置你就懂了
android{
// 渠道包定義,預設定義的名稱就是渠道名稱
productFlavors {
dev {} // 測試
baidu {} // 百度手機助手
yinyongbao {} // 應用寶
m360 {} // 360手機助手
pp {} // PP助手
anzhi{} // 安智市場
xiaomi {} // 小米商店
letv {} // 樂視商店
huawei {} // 華為商店
lenovomm {} // 聯想樂商店
other {} // 其他市場
official{} // 官方版本
}
// 批量渠道包值替換
productFlavors.all { flavor ->
// 友盟、極光推送渠道包, UMENG_CHANNEL 是根據你AndroidManifest.xml來配置的,請看下麵。
flavor.manifestPlaceholders = [UMENG_CHANNEL: name, JPUSH_CHANNEL: name]
}
}
AndroidManifest.xml
配置:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.rae.demo">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<!--變數採用${變數名}這樣來替換,不僅限與<meta-data /> 標簽,任何你想替換的都行。-->
<meta-data
android:name="UMENG_APPKEY"
android:value="${UMENG_APPKEY}"/>
<meta-data
android:name="UMENG_CHANNEL"
android:value="${UMENG_CHANNEL}"/>
<!--${變數隨變換}-->
<activity
android:name=".DemoActivity"
android:label="${變數隨變換}"/>
</application>
</manifest>
sync gradle之後看看gradle projects 面板列表就多出了好到渠道的任務了,Build Variants 面板也相對應多了這些構建類型。
APK輸出配置
在結合到多渠道打包後,運營的那邊希望我們給的渠道包是這種格式的app-{版本號}-{渠道名稱}.apk
,那我們來看看怎麼來滿足這個多渠道打包輸出apk文件名修改的。
android{
// 輸出文件配置
applicationVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.apk')) {
def dirName = outputFile.parent // 輸出文件夾所在的位置
// 文件名修改
def fileName = "app-${output.processResources.variantName}-${defaultConfig.versionName}-${variant.flavorName}.apk"
// 比如不想這麼麻煩,直接在後面加上版本號也行:
// def fileName = outputFile.name.replace(".apk", "-${defaultConfig.versionName}.apk")
output.outputFile = new File(dirName, fileName)
}
}
}
}