Android專案框架思考--配置檔案
很早就想寫一些相關的技術文件,一來鍛鍊自己的書寫能力,二來也能記錄自己的成長痕跡。每過一段時間寫一篇技術文章,希望自己能夠一直堅持下去。
一個合適的框架能夠讓專案開發順暢,程式碼條理清晰、功能實現效率提升,以及執行時減少很多人為水平原因的錯誤。
為了能夠讓專案多人並行快速高質量開發,在開發前期我們可以做很多事情來較少後期重複的工作量,本次梳理一下一個專案的配置資訊如何統一管理。一個專案中包含application以及其他作為lib庫的module,他們的build.gradle都有一些配置資訊,將配置資訊統一化,一方面便於後期快速更改專案的編譯環境,另一方方面也能快速的使他人接入開發,不會因為電腦環境變數的改變而花費很多時間來回修改mudle的配置引數。
我們通過AndroidStudio建立一個預設的專案時,其配置檔案大題如下:
application中的build.gradle
apply plugin: 'com.android.application' android { compileSdkVersion 26 defaultConfig { applicationId "com.kotlin.anonyper.testapplication" minSdkVersion 15 targetSdkVersion 26 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } compileOptions { targetCompatibility 1.8 sourceCompatibility 1.8 } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:26.1.0' implementation 'com.android.support.constraint:constraint-layout:1.1.3' }
module中的build.gradle
apply plugin: 'com.android.library' android { compileSdkVersion 26 defaultConfig { minSdkVersion 15 targetSdkVersion 26 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:26.1.0' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' }
可以看到上面,每一個build.gradle中都有compileSdkVersion、defaultConfig等資訊(在module中有一些引數是非必要),加上我們直接從網路上下載的第三方module他們的配置引數很大可能和上面的不一樣,這樣就導致同一個專案在不同的電腦上都需要一個一個的module去調整配置資訊,而這個過程對於新手來說稍不留神就是非常痛苦的。所以我們可以將這些共同的引數提取出來,寫到同一個地方。
專案的根目錄下有一個叫做gradle.properties的檔案,我們可以在這裡寫一些專案所需要的公共引數,以便於不同的module來使用:
gradle.properties樣例
# Project-wide Gradle settings. # IDE (e.g. Android Studio) users: # Gradle settings configured through the IDE *will override* # any settings specified in this file. # For more details on how to configure your build environment visit # http://www.gradle.org/docs/current/userguide/build_environment.html # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. # Default value: -Xmx10248m -XX:MaxPermSize=256m # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true ################################################### #############gradle 優化(確實快了不少) ############# ################################################### # Project-wide Gradle settings. # IDE (e.g. Android Studio) users: # Settings specified in this file will override any Gradle settings # configured through the IDE. # For more details on how to configure your build environment visit # http://www.gradle.org/docs/current/userguide/build_environment.html # The Gradle daemon aims to improve the startup and execution time of Gdradle. # When set to true the Gradle daemon is to run the build. # TODO: disable daemon on CI, since builds should be clean and reliable on servers org.gradle.daemon=true # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. # Default value: -Xmx10248m -XX:MaxPermSize=256m org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects org.gradle.parallel=true # Enables new incubating mode that makes Gradle selective when configuring projects. # Only relevant projects are configured which results in faster builds for large multi-projects. # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:configuration_on_demand org.gradle.configureondemand=true # 版本編譯配置 ANDROID_BUILD_MIN_SDK_VERSION=15 ANDROID_BUILD_TARGET_SDK_VERSION=26 ANDROID_BUILD_SDK_VERSION=26 ANDROID_BUILD_TOOLS_VERSION=26.0.0 # 版本號、包名等配置 APPLICATION_ID=com.kotlin.anonyper.testapplication ANDROID_BUILD_VER_CODE=1 ANDROID_BUILD_VER_NAME=1.0 # 簽名證書配置 STORE_FILE=/Users/Documents/tianqismart/xxx.jks STORE_PASSWORD=xxx1234 KEY_ALIAS=xxxx KEY_PASSWORD=xxx1234 #平臺引數配置 GAODE_APPKEY=b5743c922cb683eff0d090272b4aa571 JPUSH_APPKEY=1d732d903966481323ca4c7f # 解決RN64位相容 android.useDeprecatedNdk=true #java版本 JAVA_VERSION=1.8 #gradle版本 GRADLE_VERSION=3.0.1
在appliciton的build.gradle中使用
apply plugin: 'com.android.application' //key為 gradle.properties裡定義的變數 //編譯的sdk版本 def ANDROID_BUILD_SDK_VERSION = project.getProperties().get("ANDROID_BUILD_SDK_VERSION") if (ANDROID_BUILD_SDK_VERSION == null) { ANDROID_BUILD_SDK_VERSION = "26" //給出預設值 } //app min sdk version def ANDROID_BUILD_MIN_SDK_VERSION = project.getProperties().get("ANDROID_BUILD_MIN_SDK_VERSION") if (ANDROID_BUILD_MIN_SDK_VERSION == null) { ANDROID_BUILD_MIN_SDK_VERSION = "15" //給出預設值 } //app target sdk version def ANDROID_BUILD_TARGET_SDK_VERSION = project.getProperties().get("ANDROID_BUILD_TARGET_SDK_VERSION") if (ANDROID_BUILD_TARGET_SDK_VERSION == null) { ANDROID_BUILD_TARGET_SDK_VERSION = "1" //給出預設值 } //app version code def ANDROID_BUILD_VER_CODE = project.getProperties().get("ANDROID_BUILD_VER_CODE") if (ANDROID_BUILD_VER_CODE == null) { ANDROID_BUILD_VER_CODE = "1" //給出預設值 } //app version name def ANDROID_BUILD_VER_NAME = project.getProperties().get("ANDROID_BUILD_VER_NAME") if (ANDROID_BUILD_VER_NAME == null) { ANDROID_BUILD_VER_NAME = "1.0" //給出預設值 } //編譯的tools版本 def ANDROID_BUILD_TOOLS_VERSION = project.getProperties().get("ANDROID_BUILD_TOOLS_VERSION") if (ANDROID_BUILD_TOOLS_VERSION == null) { ANDROID_BUILD_TOOLS_VERSION = "26.0.0" //給出預設值 } //app的包名 def ANDROID_APPLICATION_ID = project.getProperties().get("APPLICATION_ID") if (ANDROID_APPLICATION_ID == null) { ANDROID_APPLICATION_ID = "com.kotlin.anonyper.testapplication" //給出預設值 } //高德key def GAODE_APPKEY = project.getProperties().get("GAODE_APPKEY") //極光key def JPUSH_APPKEY = project.getProperties().get("JPUSH_APPKEY") //簽名檔案地址 def STORE_FILE = project.getProperties().get("STORE_FILE") if (STORE_FILE == null) { STORE_FILE = "/Users/Documents/tianqismart/xxx.jks" //給出預設值 } //簽名檔案的密碼 def STORE_PASSWORD = project.getProperties().get("STORE_PASSWORD") if (STORE_PASSWORD == null) { STORE_PASSWORD = "xxxx1234" //給出預設值 } //簽名檔案別名 def KEY_ALIAS = project.getProperties().get("KEY_ALIAS") if (KEY_ALIAS == null) { STORE_PASSWORD = "xxxx" //給出預設值 } //編譯檔案別名對應的密碼 def KEY_PASSWORD = project.getProperties().get("KEY_PASSWORD") if (KEY_PASSWORD == null) { KEY_PASSWORD = "xxxx1234" //給出預設值 } android { compileSdkVersion Integer.parseInt(ANDROID_BUILD_SDK_VERSION as String) defaultConfig { applicationId ANDROID_APPLICATION_ID minSdkVersion Integer.parseInt(ANDROID_BUILD_MIN_SDK_VERSION as String) targetSdkVersion Integer.parseInt(ANDROID_BUILD_TARGET_SDK_VERSION as String) versionCode Integer.parseInt(ANDROID_BUILD_VER_CODE as String) versionName ANDROID_BUILD_VER_NAME manifestPlaceholders = [ GAODE_APPKEY : GAODE_APPKEY, JPUSH_PKGNAME: ANDROID_APPLICATION_ID, JPUSH_APPKEY : JPUSH_APPKEY, //JPush上註冊的包名對應的appkey. ] } signingConfigs { release { //簽名 storeFile file(STORE_FILE) storePassword STORE_PASSWORD keyAlias KEY_ALIAS keyPassword KEY_PASSWORD } } buildTypes { debug { buildConfigField "boolean", "LOG_DEBUG", "true" shrinkResources false signingConfig signingConfigs.release minifyEnabled false } release { // 不顯示Log buildConfigField "boolean", "LOG_DEBUG", "false" //是否混淆 minifyEnabled true // 移除無用的resource檔案 shrinkResources false // debuggable false jniDebuggable false zipAlignEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' signingConfig signingConfigs.release } } ompileOptions { sourceCompatibility JAVA_VERSION targetCompatibility JAVA_VERSION } } allprojects { repositories { maven { url "https://maven.google.com" } jcenter() mavenCentral() flatDir { dirs 'libs' } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:26.1.0' implementation 'com.android.support.constraint:constraint-layout:1.1.3' }
裡面的預設值可以給,可以不寫。不寫的話就必須在gradle.properties檔案中配置了用到的引數。
module中的build.gradle
apply plugin: 'com.android.library' def ANDROID_BUILD_SDK_VERSION = project.getProperties().get("ANDROID_BUILD_SDK_VERSION") if (ANDROID_BUILD_SDK_VERSION == null) { ANDROID_BUILD_SDK_VERSION = "26" //給出預設值 } //app min sdk version def ANDROID_BUILD_MIN_SDK_VERSION = project.getProperties().get("ANDROID_BUILD_MIN_SDK_VERSION") if (ANDROID_BUILD_MIN_SDK_VERSION == null) { ANDROID_BUILD_MIN_SDK_VERSION = "15" //給出預設值 } //app target sdk version def ANDROID_BUILD_TARGET_SDK_VERSION = project.getProperties().get("ANDROID_BUILD_TARGET_SDK_VERSION") if (ANDROID_BUILD_TARGET_SDK_VERSION == null) { ANDROID_BUILD_TARGET_SDK_VERSION = "1" //給出預設值 } //app version code def ANDROID_BUILD_VER_CODE = project.getProperties().get("ANDROID_BUILD_VER_CODE") if (ANDROID_BUILD_VER_CODE == null) { ANDROID_BUILD_VER_CODE = "1" //給出預設值 } //app version name def ANDROID_BUILD_VER_NAME = project.getProperties().get("ANDROID_BUILD_VER_NAME") if (ANDROID_BUILD_VER_NAME == null) { ANDROID_BUILD_VER_NAME = "1.0.0" //給出預設值 } //編譯的tools版本 def ANDROID_BUILD_TOOLS_VERSION = project.getProperties().get("ANDROID_BUILD_TOOLS_VERSION") if (ANDROID_BUILD_TOOLS_VERSION == null) { ANDROID_BUILD_TOOLS_VERSION = "26.0.0" //給出預設值 } android { compileSdkVersion Integer.parseInt(ANDROID_BUILD_SDK_VERSION as String) defaultConfig { minSdkVersion Integer.parseInt(ANDROID_BUILD_MIN_SDK_VERSION as String) targetSdkVersion Integer.parseInt(ANDROID_BUILD_TARGET_SDK_VERSION as String) versionCode Integer.parseInt(ANDROID_BUILD_VER_CODE as String) versionName ANDROID_BUILD_VER_NAME } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:26.1.0' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' }
多個module時候配置同上。這樣我們就將相關的引數都統一到一個檔案中,以後切換、修改引數也只需要修改一個地方其他地方都會同步過來。
以上只是簡單的抽離了配置的引數,其實引入的第三方lib的版本也可以統一在一個地方配置,同時除了將配置資訊統一寫到gradle.properties中之外,也可以將引數寫在專案根目錄的build.gradle中,如下:
// Top-level build file where you can add configuration options common to all sub-projects/modules. def GRADLE_VERSION = project.getProperties().get("GRADLE_VERSION") buildscript { repositories { google() jcenter() } dependencies { classpath "com.android.tools.build:gradle:${GRADLE_VERSION}" } } allprojects { repositories { google() jcenter() } } task clean(type: Delete) { delete rootProject.buildDir } ext { // Sdk and tools compileSdkVersion = 26 supportLibraryVersion = '26.1.0' constraintLayoutVersion = '1.1.3' //其他引數 }
上面的ext裡面就是引數的配置,具體使用方法:
compileSdkVersion Integer.parseInt("$rootProject.ext.compileSdkVersion" as String) 或者: dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "com.android.support:appcompat-v7:$rootProject.ext.supportLibraryVersion" }