Android Gradle 常用使用場景實現方式的總結

亦楓發表於2017-09-16

Gradle 作為一款靈活多變的構建外掛,與 Android Studio 的結合,能夠解決過去使用 Eclipse 開發 App 時所遇到的諸多問題。同時,基於 Groove 這樣一款 DSL 語言的指令碼特性,記住各種語法顯然又是一件比較困難的事情。

事實上,Gradle 外掛的常用使用場景並不是很多,也不需要死記硬背,或者完全學會 Groove 的所有使用方式。這裡將 Android 開發中較為常用的 Gradle 使用場景總結出來,用於將來需要的時候有個參考。

多渠道打包

舉一個最常見的多渠道使用場景,友盟統計,看看最基本的 Gradle 多渠道打包方式的用法。

修改 Manifest 檔案中友盟統計的渠道名為引用變數(變數名自取):

<meta-data
    android:name="${UMENG_CHANNEL_VALUE}"
    android:value="Channel_ID" />複製程式碼

然後在 build.gradle 檔案 productFlavors 配置項中新增渠道名,並統一設定到上面提到的變數名:

android {
    productFlavors {
        xiaomi {}
        yingyongbao {}
    }

    productFlavors.all {
        flavor -> flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
    }
}複製程式碼

執行打包 Task 的命令語句即可:

./gradle assembleRelease複製程式碼

或者有針對性的只打特定渠道包,如:

./gradle assembleXiaomiRelease複製程式碼

備註:在 Gradle projects 視窗中能夠檢視所有可執行的 Tasks 列表。這種原生態打包方式適合渠道名比較少的使用場景。當渠道多達數十個甚至上百個時,打包時間就會比較長,推薦其他打包方案,如:

自定義輸出 APK 檔名

可以修改打包輸出的 apk 檔名,新增時間戳、編譯型別、版本資訊等關鍵字,是 apk 檔案更具識別性,如:

apply plugin: 'com.android.application'

def releaseTime() {
    return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC"))
}

android {
    android.applicationVariants.all { variant ->
        variant.outputs.each { output ->
            output.outputFile = new File(output.outputFile.parent, rootProject.getName()
                    + "-" + buildType.name
                    + "-" + releaseTime()
                    + "-v" + defaultConfig.versionName
                    + "-" + defaultConfig.versionCode
                    + ".apk");
        }
    }
}複製程式碼

這裡將專案名稱新增到 apk 檔名中,也可以使用 applicationId 等,結果如下:

YFSample-release-2017-09-12-v1.0-1.apk複製程式碼

Debug 和 Release 相同簽名

android {
    buildTypes {
        debug {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            buildConfigField "boolean", "DEBUG_MODE", "true"
            signingConfig signingConfigs.config
        }
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            buildConfigField "boolean", "DEBUG_MODE", "false"
            signingConfig signingConfigs.config
        }
    }
}複製程式碼

這一步操作可以通過圖形化介面操作,更方便一些。右鍵專案,點選 Open Module Settings,開啟 Project Structure 視窗,在 Build Types 選項卡中設定。

隱藏簽名資訊

簽名資訊作為專案裡最為私密的一部分內容,如果直接暴露在 build.gradle 檔案中,顯然不夠安全。尤其是需要上傳到 GitHub 等託管平臺時。

比較妥當的做法是,在專案根目錄下新建一個專門用來儲存簽名資訊的檔案,並且將其新增到 ignore 檔案配置當中。具體操作過程如下:

第一步,新建一個 keystore.properties 檔案:

ReleaseKeyPassword=sampleKeyPwd
ReleaseKeyAlias=sampleAlias
ReleaseStorePassword=sampleStorePwd
ReleaseStoreFile=../sample.jks複製程式碼

第二步,在 build.gradle 檔案的最外層引入簽名資訊:

allprojects {
    afterEvaluate { project ->
        def propsFile = rootProject.file('keystore.properties')
        def configName = 'config'

        if (propsFile.exists() && android.signingConfigs.hasProperty(configName)) {
            def props = new Properties()
            props.load(new FileInputStream(propsFile))
            android.signingConfigs[configName].storeFile = file(props['ReleaseStoreFile'])
            android.signingConfigs[configName].storePassword = props['ReleaseStorePassword']
            android.signingConfigs[configName].keyAlias = props['ReleaseKeyAlias']
            android.signingConfigs[configName].keyPassword = props['ReleaseKeyPassword']
        }
    }
}複製程式碼

如此即可。其中第二步還有一種縮減版的寫法,也可以直接使用:

def keystorePropertiesFile = rootProject.file("keystore.properties");
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))

android {
    signingConfigs {
        config {
            storeFile file(keystoreProperties['ReleaseStoreFile'])
            storePassword keystoreProperties['ReleaseStorePassword']
            keyAlias keystoreProperties['ReleaseKeyAlias']
            keyPassword keystoreProperties['ReleaseKeyPassword']
        }
    }
}複製程式碼

當然,隱藏簽名資訊的方式還有很多。比如配置在本地環境變數中,或者 build.gradle 檔案中,或者編譯時從命令列中動態讀取輸入內容等,設定不同,讀取方式有所不同。

日誌開關

在 app/build.gradle 檔案中分別定義 debug 和 release 不同編譯模式的控制變數,變數名可自由更改:

buildTypes {
    debug {
        buildConfigField "boolean", "DEBUG_MODE", "true"
    }
    release {
        buildConfigField "boolean", "DEBUG_MODE", "false"
    }
}複製程式碼

重新編譯後,自動生成的 BuildConfig 類中包含上面定義的 DEBUG_MODE 屬性,即可使用。

Log 日誌開關更多解決方案,可參考:Android 中能夠作為 Log 開關的一些操作以及安全性淺談

環境分離

開發中測試伺服器和生產伺服器的同時使用也是很常見的場景之一,如何在一臺裝置中同時安裝配置測試環境的 debug 包和生產環境的 release 包,也是需要面對的問題。不妨參考我的這篇文章:

Android 利用 Gradle 實現 app 的環境分離

參考連結

學習有關 Android、Gradle 和 Groove 更多詳細資訊,除了訪問 Gradle 官方網站,推薦你閱讀這些文章:

END

關於我:亦楓,部落格地址:yifeng.studio/,新浪微博:IT亦楓

微信掃描二維碼,歡迎關注我的個人公眾號:安卓筆記俠

不僅分享我的原創技術文章,還有程式設計師的職場遐想

相關文章