Gradle模組化配置及多渠道打包

weixin_34185560發表於2018-01-19

因為之前的習慣,每天早上會準時開啟微信,點開訂閱去找鴻洋和郭神及其他關注訂閱號推薦的文章去看,才能讓我在每天忙碌的生活中,提高自己順便了解一下外面的世界和技術的走向。
切入主題,這次是看到了郭神推薦的文章,想起了自己之前一直想總結的Gradle知識,現在總結好,分享給大家(實用篇):

一. Gradle模組化配置

1.defaultConfig預設設定
在專案根目錄新建config.gradle檔案,如下:

2139461-bbd907ef24fd3ab1.png
image.png

之後在app路徑下的build.gradle中獲取並使用:

def cfg = rootProject.ext.android
    defaultConfig {
        applicationId "applicationId"
        minSdkVersion cfg.minSdkVersion
        targetSdkVersion cfg.targetSdkVersion
        versionName cfg.versionName
        versionCode cfg.versionCode
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

        multiDexEnabled true
    }

這種方式能夠將我們的gradle統一進行管理。
注:config.gradle檔案中的versionNameversionCode我是放在了專案中gradle.properties檔案中來管理,用來記錄版本發版時間和版本簡要註釋,如下圖:

2139461-25d58fd35c12b5b9.png
image.png

2.url地址優化
按照config的配置,一般來講,我們開發的時候至少會有兩個伺服器地址,正式跟測試,你每切換一次,都需要重新同步一下,還有就是,多人協作開發的時候,每次從Git伺服器上面更新程式碼,只要更新到app目錄下的gradle,都是需要重新同步的,參照config的配置,我們如果是引用的話就每次只需要讀取引用的那個url,切換隻需要修改config中的程式碼就可以了,下面是進行的優化:

   url = [
            "debug"  : "debugUrl1",
            //"debug"  : "debugUrl2",
            //"debug"  : "debugUrl3",
            "release": "releaseUrl1",
            // "release": "releaseUrl2"
    ]

app路徑下的build.gradle中獲取並使用:

def url = rootProject.ext.url
    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            buildConfigField "String", "AlphaUrl", "\"${url["release"]}\""
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.config
        }

        debug {
            minifyEnabled true
            shrinkResources true
            debuggable true
            buildConfigField "String", "AlphaUrl", "\"${url["debug"]}\""
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.config
        }
    }

這樣的話,在打包的時候直接選擇就好了,release/debug;直接在真機或者模擬器上執行的話為debug版本。


2139461-538aa655258084c1.png
image.png

3.第三方開源庫和元件版本號的管理
config中新增:

    libsVersion = [
            // 第三方庫版本號的管理
            supportLibraryVersion = "26.1.0",
            constraintlayout = "1.0.2",
            recyclerview = "26.1.0",
            cardview = "26.1.0",
            butterknife = "8.8.1",
    ]
//  依賴庫管理 compile "com.facebook.react:react-native:+"
    dependencies = [
            "appcompatV7"     : "com.android.support:appcompat-v7:$rootProject.supportLibraryVersion",
            "cardview"        : "com.android.support:cardview-v7:$rootProject.cardview",
            "recycleview"     : "com.android.support:recyclerview-v7:$rootProject.recyclerview",
            "constraintlayout": "com.android.support.constraint:constraint-layout:$rootProject.constraintlayout",
            "butterknife"     : "com.jakewharton:butterknife:$rootProject.butterknife",
    ]

app路徑下的build.gradle中獲取並使用:

def librarys = rootProject.ext.dependencies
dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
    annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
    debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.4'
    releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4'
  //實際上librarys就是一個Map,我們可以寫一個迴圈來簡化這些程式碼,就跟HashMap的遍歷一樣,這裡我只挑選了compile :
    librarys.each { k, v -> compile v }
}

二. 多渠道打包

1.讓簽名資訊保安
在專案根目錄的keystore.properties檔案中設定好key金鑰和路徑,這個檔案是存在本地的(如果沒有這個檔案,就新建)。

2139461-cca0d9cdc3c68ac7.png
image.png

之後在build.gradle檔案中設定簽名檔案資訊,如圖:
首先獲取到簽名檔案
2139461-49c87aafdd02b43a.png
image.png

然後設定簽名資訊
2139461-253f0586ecf39321.png
image.png

當然,這一步也可以不設定,直接在build.gradle檔案中新增簽名資訊:
2139461-206fc1d276a0bb01.png
image.png

2.多渠道打包配置:productFlavors 用法
productFlavors顧名思義,就是用來分別定義產品不同的特性,使用它可以用一套程式碼建立不同的產品
就是用於定義產品的特性,這是每個產品不同的地方。有了它我們可以用同一套程式碼建立不同的產品。設定productFlavors的方法如下:
build.gradle檔案中加入productFlavors結構:

android{
    ......
    productFlavors{
        productA{
            //這裡定義產品A的特性
        }

        productB{
            //這裡定義產品B的特性
        }

       //更多產品 ...
    }

設定渠道包資訊:

    //友盟多渠道打包
    flavorDimensions "Yin"
    productFlavors {
        wandoujia {
            versionName = project.VERSION_NAME
            dimension "Yin"
        }
        _360 {
            dimension "Yin"
        }
        huawei {
            dimension "Yin"
        }
        xiaomi {
            dimension "Yin"
        }
        meizu {
            dimension "Yin"
        }
        vivo {
            dimension "Yin"
        }
    }

    productFlavors.all { flavor ->
        manifestPlaceholders.put("UMENG_CHANNEL_VALUE", name)
    }

注:這裡用的還是友盟的關鍵字;為了適配gradle
3.0還,在使用flavor時,必須定義flavorDimension,還需要在AndroidManifest.xml檔案中新增:

2139461-195f2e02f5d02c61.png
image.png

最後,在buildTypesrelease設定中新增下面這段程式碼(批量修改生成的apk檔名):
2139461-ffd7deff2948437f.png
image.png

注:可能出現的錯誤:

//Gradle升級了3.0後,output.outputFile變成了只讀屬性,不能再往裡面寫東西了,以下是3.0之前的配置:

applicationVariants.all { variant ->    //批量修改Apk名字
    variant.outputs.each { output ->
        def outputFile = output.outputFile
        if (outputFile != null && outputFile.name.endsWith('.apk') && 'release'.equals(variant.buildType.name)) {
            def fileName = outputFile.name.replace("${variant.flavorName}", "V${defaultConfig.versionName}-${variant.flavorName}")
            fileName = fileName.replace('.apk', "-${buildTime()}.apk")
            output.outputFile = new File(outputFile.parent, fileName)
        }
    }
}
//下面是經過修改之後3.0裡面批量修改APK名字的配置:

applicationVariants.all { variant ->    //批量修改Apk名字
    variant.outputs.all { output ->
        if (!variant.buildType.isDebuggable()) {
            //獲取簽名的名字 variant.signingConfig.name
            //要被替換的源字串
            def sourceFile = "-${variant.flavorName}-${variant.buildType.name}"
            //替換的字串
            def replaceFile = "_V${variant.versionName}_${variant.flavorName}_${variant.buildType.name}_${buildTime()}"
            outputFileName = output.outputFile.name.replace(sourceFile, replaceFile);          
        }
    }
}

3.多渠道打包
在AS上直接像平時一樣打包,只不過在選擇路徑的時候有了更多的選擇,可以單獨打一個標籤的,也可以多選打出各個渠道的包,如圖:

2139461-f3938ed57b03f586.png
image.png

好了,大功告成。歡迎大家吐槽,這個Gradle東西太多,我只總結了,我用到的部分。關於Gradle詳解可以在下面的參考連結中學習。

最後附上,專案地址:Gradle模組化配置及多渠道打包

三. 參考連結

1.一個完整Android專案所需要用到的gradle配置技巧
2.Gradle模組化配置:讓你的gradle程式碼控制在100行以內
3.終極元件化框架專案方案詳解
4.Android開發中Gradle配置的相關概念
5.Cannot set the value of read-only property 'outputFile' for ApkVariantOutputImpl_Decorated

相關文章