摘要:例如默認配置項簽名相關構建變體產品風格源集配置等。例如你想修改為的名稱,這時你可以使用這樣在下的包名都是以打頭會幫助我們創建默認的源集與目錄位于,用來存儲所有構建變體間的共享資源。
上次我們說到gradle的原理,主要是偏理論上的知識點,直通車在這Android Gradle系列-原理篇。這次我們來點實戰的,隨便鞏固下之前的知識點。
android在app module下的gradle.build中都有一個android閉包,主要配置都在這里設置。例如默認配置項:defaultConfig;簽名相關:signingConfig;構建變體:buildTypes;產品風格:productFlavors;源集配置:sourceSets等。
defaultConfig對于defaultConfig其實它是也一個productFlavor,只不過這里是用來提供默認的設置項,如果之后的productFlavor沒有特殊指定的配置都會使用defaultConfig中的默認配置。
public class DefaultConfig extends BaseFlavor { @Inject public DefaultConfig( @NonNull String name, @NonNull Project project, @NonNull ObjectFactory objectFactory, @NonNull DeprecationReporter deprecationReporter, @NonNull Logger logger) { super(name, project, objectFactory, deprecationReporter, logger); } } public abstract class BaseFlavor extends DefaultProductFlavor implements CoreProductFlavor { ... }
可以看到defaultConfig的超級父類就是DefaultProductFlavor。而在DefaultProductFlavor中定義了許多我們經常見到的配置:VersionCode、VersionName、minSdkVersion、targetSdkVersion與applicationId等等。
有了上面的基礎,那么在defaultConfig中我們要配置的變量就顯而易見了。
defaultConfig { applicationId "com.idisfkj.androidapianalysis" minSdkVersion 16 targetSdkVersion 26 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" }signingConfigs
signingConfig是用來配置keyStore,我們可以針對不同的版本配置不同的keyStore,例如
signingConfigs { config { //默認配置 storeFile file("key.store") storePassword "android123" keyAlias "android" keyPassword "android123" } dev { //dev測試版配置 storeFile file("xxxx") storePassword "xxx" keyAlias "xxx" keyPassword "xxx" } }
有人可能會說這不安全的,密碼都是明文,都暴露出去了。是的,如果這項目發布到遠程,那么這些秘鑰就泄露出去了。所以為了安全起見,我們可以對其進一些特殊處理。
通過環境變量獲取秘鑰
storePassword System.getenv("KSTOREPWD") keyPassword System.getenv("KEYPWD")
從命令行中獲取秘鑰
storePassword System.console().readLine(" Keystore password: ") keyPassword System.console().readLine(" Key password: ")
上面兩種是Android Develop官網提供的,但經過測試都會報null異常,查了下資料都說是gradle不支持(如果有成功的可以告知我),所以還是推薦下面的這種方法
在項目的根目錄下(settings.gradle平級)創建keystore.properties文件,我們在這個文件中進行存儲秘鑰,它是支持key-value模式的鍵值對數據
storePassword = android123 keyPassword = android123
之后就是讀取其中的password,在build.gradle通過afterEvaluate回調進行讀取與設置
afterEvaluate { 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].keyPassword = props["keyPassword"] android.signingConfigs[configName].storePassword = props["storePassword"] } }
我們已經通過動態讀取了password,所以在之前的signingConfigs中就無需再配置password
signingConfigs { config { storeFile file("key.store") keyAlias "android" } }
最后一步,為了保證秘鑰的安全性,在.gitignore中添加keystore.properties的忽略配置,防止上傳到遠程倉儲暴露秘鑰。
buildTypes構建變體主要用來配置shrinkResources:資源是否需要壓縮、zipAlignEnabled:壓縮是否對齊、minifyEnabled:是否代碼混淆與signingConfig:簽名配置等等。新建項目時,默認有一個release配置,但我們實際開發中可能需要多個不同的配置,例如debug模式,為了方法調試,一般都不需要對其進行代碼混淆、壓縮等處理。或者outer模式,需要的簽名配置不同,所以最終的配置可以是這樣:
buildTypes { debug { minifyEnabled false zipAlignEnabled false shrinkResources false signingConfig signingConfigs.config } outer { minifyEnabled false zipAlignEnabled false shrinkResources false signingConfig signingConfigs.outConfig } release { minifyEnabled true zipAlignEnabled true shrinkResources true signingConfig signingConfigs.config proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" } }
Sync Now之后,打開Android Studio 右邊的Gradle,找到app->Tasks->build,發現已經添加了assembleDebug與assembleOuter構建task。
productFlavors一個項目可能有不同的版本環境,例如開發功能中的開發版、項目上線的正式版。開發版與正式版請求的數據api可能不同,對于這種情況我們就可以使用productFlavor來構建不同的產品風格,可以看下面的dev與prod配置
flavorDimensions "mode" productFlavors { dev { applicationIdSuffix ".dev" dimension "mode" manifestPlaceholders = [PROJECT_NAME: "@string/app_name_dev", APP_ID : "21321843"] buildConfigField "String", "API_URL", ""https://dev.idisfkj.android.com"" buildConfigField "String", "APP_KEY", ""3824yk32"" } prod { applicationIdSuffix ".prod" dimension "mode" manifestPlaceholders = [PROJECT_NAME: "@string/app_name", APP_ID : "12932843"] buildConfigField "String", "API_URL", ""https://prod.idisfkj.android.com"" buildConfigField "String", "APP_KEY", ""32143dsk2"" } }
對于判斷是否為同一個app,手機系統是根據app的applicationId來識別的,默認applicationId是packageName。所以為了讓dev與prod的版本都能共存在一個手機上,可以通過applicationIdSuffix來為applicationId增加后綴,改變安裝包的唯一標識。
還有可以通過manifestPlaceholders來配置可用于AndroidManifest中的變量,例如根據不同的產品風格顯示不同的app名稱
dev與prod網絡請求時使用不同的api host,可以設置buildConfigField,這樣我們就可以在代碼中通過BuildConfig獲取
fun getApiUlr(): String { return BuildConfig.API_URL }
這里的BuildConfig會根據你構建的產品風格返回不同的值,它位于build->generated->source->buildConfig->變體,大致內容如下:
public final class BuildConfig { public static final boolean DEBUG = Boolean.parseBoolean("true"); public static final String APPLICATION_ID = "com.idisfkj.androidapianalysis.dev"; public static final String BUILD_TYPE = "debug"; public static final String FLAVOR = "devMinApi21"; public static final int VERSION_CODE = 20001; public static final String VERSION_NAME = "1.0-minApi21"; public static final String FLAVOR_mode = "dev"; public static final String FLAVOR_api = "minApi21"; // Fields from product flavor: dev public static final String API_URL = "https://dev.idisfkj.android.com"; public static final String APP_KEY = "3824yk32"; }
Sync Now之后,打開Android Studio 右邊的Gradle,找到app->Tasks->build,發現新添加了assembleDev與assembleProd構建task。
flavorDimensions是用來設置多維度的,上面的例子只展示了一個維度,所以dimension為mode的形式。我們新增一個api維度,構建不同的minSkdVerison版本的apk
flavorDimensions "mode", "api" productFlavors { dev { applicationIdSuffix ".dev" dimension "mode" manifestPlaceholders = [PROJECT_NAME: "@string/app_name_dev", APP_ID : "21321843"] buildConfigField "String", "API_URL", ""https://dev.idisfkj.android.com"" buildConfigField "String", "APP_KEY", ""3824yk32"" } prod { applicationIdSuffix ".prod" dimension "mode" manifestPlaceholders = [PROJECT_NAME: "@string/app_name", APP_ID : "12932843"] buildConfigField "String", "API_URL", ""https://prod.idisfkj.android.com"" buildConfigField "String", "APP_KEY", ""32143dsk2"" } minApi16 { dimension "api" minSdkVersion 16 versionCode 10000 + android.defaultConfig.versionCode versionNameSuffix "-minApi16" } minApi21 { dimension "api" minSdkVersion 21 versionCode 20000 + android.defaultConfig.versionCode versionNameSuffix "-minApi21" } }
gradle創建的構建變體數量等于每個風格維度中的風格數量與你配置的構建類型數量的乘積,所以上面例子的構建變體數量為12個。在gradle為每個構建變體或對應apk命名時,屬于較高優先級風格維度的產品風格首先顯示,之后是較低優先級維度的產品風格,再之后是構建類型。而優先級的判斷則以flavorDimensions的值順序為依據,以上面的構建配置為例:
構建變體:dev, prod[debug, outer, release]
對應apk:app-[dev, prod]-[minApi16, minApi21]-[debug, outer, release].apk
構建變體有這么多,但有時我們并不全部需要,例如你不需要mode為dev,api為minApi16的變體,這時你就可以使用variantFilter方法來過濾
variantFilter { variant -> def names = variant.flavors*.name if (names.contains("minApi16") && names.contains("dev")) { setIgnore(true) } }
你再回到app->Tasks中查看變體,會發現已經將devMinApi16相關的變體過濾了。
你不僅可以過濾構建變體,還可以改變默認的apk輸出名稱。例如你想修改buildType為release的apk名稱,這時你可以使用android.applicationVariants.all
android.applicationVariants.all { variant -> if (variant.buildType.name == buildTypes.release.name) { variant.outputs.all { outputFileName = "analysis-release-${defaultConfig.versionName}.apk" } } }
這樣在release下的包名都是以analysis打頭
sourceSetsAndroid Studio會幫助我們創建默認的main源集與目錄(位于app/src/main),用來存儲所有構建變體間的共享資源。所以你可以通過設置main源集來更改默認的配置。例如現在你想將res的路徑修改成src/custom/res
sourceSets { main { res.srcDirs = ["src/custom/res"] } }
這樣res資源路徑就定位到了src/custom/res下,當然你也可以修改其它的配置,例如java、assets、jni等。
如果你配置了多個路徑,即路徑集合:
sourceSets { main { res.srcDirs = ["src/custom/res", "scr/main/res"] } }
這時你要保證不能有相同的名稱,即每個文件只能唯一存在其中一個目錄下。
你也可以查看所以的構建變體的默認配置路徑: 點擊右邊gradle->app->android->sourceSets,你將會看到如下類似信息
------------------------------------------------------------ Project :app ------------------------------------------------------------ androidTest ----------- Compile configuration: androidTestCompile build.gradle name: android.sourceSets.androidTest Java sources: [app/src/androidTest/java] Manifest file: app/src/androidTest/AndroidManifest.xml Android resources: [app/src/androidTest/res] Assets: [app/src/androidTest/assets] AIDL sources: [app/src/androidTest/aidl] RenderScript sources: [app/src/androidTest/rs] JNI sources: [app/src/androidTest/jni] JNI libraries: [app/src/androidTest/jniLibs] Java-style resources: [app/src/androidTest/resources] ...
上面是androidTest變體的默認路徑,首先它會去查找相應的構建變體的默認位置,如果沒有找到,就會使用main源集下的默認配置。也就是我們所熟悉的app/src/main路徑下的資源。
因為它是跟構建變體來搜索的,所以它有個優先級:
src/modeApiDebug: 構建變體
src/debug:構建類型
src/modeApi:產品風格
src/main:默認main源
對于源集的創建,如下所示在app/src下右鍵新建,但它只會幫你創建源集下的java文件夾,其它的都要你自己逐個創建
我們自定義一個debug源集,所以進去之后Target Source Set選擇debug,再點擊finish結束。這時你將會在src下看到debug文件夾
現在你已經有了debug的源集目錄,假設你現在要使debug下的app名稱展示成Android精華錄debug(默認是Android精華錄)。這時你可以右鍵debug新建values
在values目錄下新建strings.xml,然后在其中配置app_name
Android精華錄debug
最后你再去構建debug相關的變體時,你安裝的app展示的名稱將是Android精華錄debug。
所以通過修改mian源集或者配置其它的變體源集,可以實現根據變體加載不同的數據源。這樣系統化的配置加載資源將更加方便項目測試與版本需要的配置。
dependenciesdependencies閉包上用來配置項目的第三方依賴,如果你根據上面的配置有設置變體,那么你將可以根據變體來選擇性的依賴第三方庫
dependencies { implementation fileTree(dir: "libs", include: ["*.jar"]) implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" implementation "com.android.support:appcompat-v7:26.1.0" implementation "com.android.support.constraint:constraint-layout:1.0.2" 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" //根據變體選擇性依賴 outerImplementation "..." prodMinApi21Implementation "..." }
關于dependencies,這只是簡單的配置方式,之后我還會多帶帶抽出一篇文章來寫系統化的配置dependencies,感興趣的可以關注下。
gradle相關的配置還有很多,這里只是冰山一角,但我的建議是根據你的實際需求去學習與研究,相信你也會有意想不到的成長。
最后附上源碼地址:https://github.com/idisfkj/an...
博客地址:https://www.rousetime.com/
系列Android Gradle系列-入門篇
Android Gradle系列-原理篇
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/74703.html
摘要:如果你有新建一個項目的經歷,那么你將看到推薦的方案在的中使用來定義版本號全局變量。例如之前的版本號就可以使用如下方式實現因為使用的是語言,所以以上都是語法例如版本控制,上面代碼的意思就是將有個相關的版本依賴放到的變量中,同時放到了中。 showImg(https://segmentfault.com/img/bVbsh3m?w=2560&h=1280); 上篇文章我們已經將Gradle...
摘要:接下來的一段時間會對的相關知識進行梳理,所以借此整理成一個系列。所以不僅支持還支持等。所以是位于的最外層,即與同級。根據后面的提示,發現它們分別來自與與。它會在運行時注入到相應的中。 showImg(https://segmentfault.com/img/bVbsh3m?w=2560&h=1280); 接下來的一段時間會對Android Gradle的相關知識進行梳理,所以借此整理成...
閱讀 3197·2021-11-25 09:43
閱讀 3408·2021-11-11 16:54
閱讀 823·2021-11-02 14:42
閱讀 3742·2021-09-30 09:58
閱讀 3664·2021-09-29 09:44
閱讀 1279·2019-08-30 15:56
閱讀 2097·2019-08-30 15:54
閱讀 2985·2019-08-30 15:43