Android 下的 gradle 配置(一)

首先獻(xiàn)上官方文檔https://developer.android.google.cn/studio/build/gradle-tips
首先我們明確一下Android 的打包流程
https://developer.android.google.cn/studio/build/index.html

典型Android 應(yīng)用構(gòu)建流程

1充尉、編譯器①將安卓的源碼編譯為DEX文件,并將其他內(nèi)容轉(zhuǎn)為②已編譯資源醋界。
2教硫、APK打包器將 DEX 文件與已編譯資源合并③成為單個(gè) APK。
3宋列、APK打包器使用調(diào)試或發(fā)布秘鑰庫(kù)簽名④ APK昭抒。
4、APK打包器使用 zipalign⑤對(duì)其進(jìn)行優(yōu)化炼杖。
結(jié)束構(gòu)建灭返。
這里有五個(gè)問題:
1、編譯器將.java 編譯為 dex 文件的過(guò)程是怎樣的坤邪;
2熙含、其他內(nèi)容如何轉(zhuǎn)為已編譯資源的;
3艇纺、APK打包器如何將 dex 與已編譯資源合并為 apk 的怎静;
4、如何進(jìn)行簽名操作喂饥;
5消约、zipalign 是什么,以及如何對(duì) apk 進(jìn)行了優(yōu)化员帮;
project 層級(jí)的 build.gradle

/**
 * 您可以在buildscript塊中為Gradle本身配置存儲(chǔ)庫(kù)和依賴項(xiàng)或粮,
 * 這意味著您不應(yīng)在此處包含模塊的依賴項(xiàng)。 
 * 例如捞高,此塊包含Gradle的Android插件作為依賴項(xiàng)氯材,
 * 因?yàn)樗峁┝薌radle構(gòu)建Android應(yīng)用程序模塊所需的其他指令。
 */
buildscript {
    /**
     * repositories塊配置Gradle使用的repositories搜索或下載依賴項(xiàng)硝岗。 
     * Gradle預(yù)先配置對(duì)遠(yuǎn)程的支持存儲(chǔ)庫(kù)氢哮,如JCenter,Maven Central和Ivy型檀。 您也可以使用本地
     * 存儲(chǔ)庫(kù)或定義您自己的遠(yuǎn)程存儲(chǔ)庫(kù)冗尤。
     * 下面的代碼定義JCenter作為存儲(chǔ)庫(kù)Gradle應(yīng)該用來(lái)查找它的依賴項(xiàng)。
     * 使用Android Studio 3.0及更高版本創(chuàng)建的新項(xiàng)目還包括Google的Maven存儲(chǔ)庫(kù)胀溺。
     */
    repositories {
        google()
        jcenter()
    }
    /**
     * dependencies塊配置Gradle需要用于構(gòu)建項(xiàng)目的依賴項(xiàng)裂七。
     * 以下行將Gradle版本3.4.0的Android插件添加為類路徑依賴項(xiàng)。
     */
    dependencies {
        classpath 'com.android.tools.build:gradle:3.4.0'
    }
}
/**
 * allprojects塊是您配置項(xiàng)目中所有模塊使用的存儲(chǔ)庫(kù)和依賴項(xiàng)的方仓坞,
 * 例如第三方插件或庫(kù)背零。
 * 但是,您應(yīng)該在每個(gè)模塊級(jí)build.gradle文件中配置特定于模塊的賴項(xiàng)无埃。
 * 對(duì)于新項(xiàng)目徙瓶,Android Studio默認(rèn)包含JCenter和Google的Maven存儲(chǔ)庫(kù)毛雇,
 * 但它不配置任何依賴項(xiàng)(除非您選擇需要某些模板的模板)。
 */
allprojects {
    repositories {
        google()
        jcenter()
    }
}

APP 下的 build.gradle基本結(jié)構(gòu)

/**
 * The first line in the build configuration applies the Android plugin for
 * Gradle to this build and makes the android block available to specify
 * Android-specific build options.
 */
apply plugin: 'com.android.application'
/**
 * The android block is where you configure all your Android-specific
 * build options.
 */
android {
    /**
     * compileSdkVersion specifies the Android API level Gradle should use to
     * compile your app. This means your app can use the API features included in
     * this API level and lower.
     */
    compileSdkVersion 28
    /**
     * buildToolsVersion specifies the version of the SDK build tools, command-line
     * utilities, and compiler that Gradle should use to build your app. You need to
     * download the build tools using the SDK Manager.
     *
     * This property is optional because the plugin uses a recommended version of
     * the build tools by default.
     */
    buildToolsVersion "28.0.3"
    /**
     * The defaultConfig block encapsulates default settings and entries for all
     * build variants, and can override some attributes in main/AndroidManifest.xml
     * dynamically from the build system. You can configure product flavors to override
     * these values for different versions of your app.
     */
    defaultConfig {
        /**
         * applicationId uniquely identifies the package for publishing.
         * However, your source code should still reference the package name
         * defined by the package attribute in the main/AndroidManifest.xml file.
         */
        applicationId 'com.example.myapp'
        // Defines the minimum API level required to run the app.
        minSdkVersion 15
        // Specifies the API level used to test the app.
        targetSdkVersion 28
        // Defines the version number of your app.
        versionCode 1
        // Defines a user-friendly version name for your app.
        versionName "1.0"
    }
    /**
     * The buildTypes block is where you can configure multiple build types.
     * By default, the build system defines two build types: debug and release. The
     * debug build type is not explicitly shown in the default build configuration,
     * but it includes debugging tools and is signed with the debug key. The release
     * build type applies Proguard settings and is not signed by default.
     */
    buildTypes {
        /**
         * By default, Android Studio configures the release build type to enable code
         * shrinking, using minifyEnabled, and specifies the Proguard settings file.
         */
        release {
            minifyEnabled true // Enables code shrinking for the release build type.
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    /**
     * The productFlavors block is where you can configure multiple product flavors.
     * This allows you to create different versions of your app that can
     * override the defaultConfig block with their own settings. Product flavors
     * are optional, and the build system does not create them by default.
     *
     * This example creates a free and paid product flavor. Each product flavor
     * then specifies its own application ID, so that they can exist on the Google
     * Play Store, or an Android device, simultaneously.
     *
     * If you declare product flavors, you must also declare flavor dimensions
     * and assign each flavor to a flavor dimension.
     */

    flavorDimensions "tier"
    productFlavors {
        free {
            dimension "tier"
            applicationId 'com.example.myapp.free'
        }

        paid {
            dimension "tier"
            applicationId 'com.example.myapp.paid'
        }
    }

    /**
     * The splits block is where you can configure different APK builds that
     * each contain only code and resources for a supported screen density or
     * ABI. You'll also need to configure your build so that each APK has a
     * different versionCode.
     */

    splits {
        // Settings to build multiple APKs based on screen density.
        density {

            // Enable or disable building multiple APKs.
            enable false

            // Exclude these densities when building multiple APKs.
            exclude "ldpi", "tvdpi", "xxxhdpi", "400dpi", "560dpi"
        }
    }
}

/**
 * The dependencies block in the module-level build configuration file
 * specifies dependencies required to build only the module itself.
 * To learn more, go to Add build dependencies.
 */

dependencies {
    implementation project(":lib")
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation fileTree(dir: 'libs', include: ['*.jar'])
}

1侦镇、android插件的引入灵疮,使得 android{}部分可用
2、android 配置
3虽缕、dependences 依賴配置
首先來(lái)看 android {}部分
我們看看都支持哪些配置字段:

aaptOptions {}//指定Android資產(chǎn)包裝工具(AAPT)的選項(xiàng)始藕。
adbOptions {}//指定Android調(diào)試橋(ADB)的選項(xiàng)蒲稳,例如APK安裝選項(xiàng)氮趋。
buildTypes {}//封裝此項(xiàng)目的所有構(gòu)建類型配置。
compileOptions {}//指定Java編譯器選項(xiàng)江耀,例如Java源代碼的語(yǔ)言級(jí)別和生成的字節(jié)碼剩胁。
dataBinding {}//指定數(shù)據(jù)綁定庫(kù)的選項(xiàng)。
defaultConfig {}//指定Android插件適用于所有構(gòu)建變體的變體屬性的默認(rèn)值祥国。
dexOptions {}//指定DEX工具的選項(xiàng)昵观,例如啟用庫(kù)預(yù)處理。
externalNativeBuild {}//使用CMake或ndk-build配置外部本機(jī)構(gòu)建舌稀。
jacoco {}//配置用于脫機(jī)檢測(cè)和覆蓋率報(bào)告的JaCoCo版本啊犬。
lintOptions {}//指定lint工具的選項(xiàng)。
packagingOptions {}//指定用于確定Android插件將哪些文件打包到APK中的選項(xiàng)和規(guī)則壁查。
productFlavors {}//封裝此項(xiàng)目的所有產(chǎn)品風(fēng)格配置觉至。
簽名會(huì)話{}//封裝可應(yīng)用于BuildType和ProductFlavor配置的簽名配置。
sourceSets {}//封裝所有變體的源集配置睡腿。
splits{}//指定用于構(gòu)建多個(gè)APK或APK拆分的配置语御。
testOptions {}//指定Android插件應(yīng)如何運(yùn)行本地和檢測(cè)測(cè)試的選項(xiàng)。

詳細(xì)說(shuō)明祭出 google 文檔 plugins:'com.android.application'
挑幾個(gè)常用的說(shuō)一下
首先新建項(xiàng)目時(shí)自動(dòng)會(huì)生成的 defaultConfig{}
指定Android插件適用于所有構(gòu)建變體的變體屬性的默認(rèn)值席怪。
配置產(chǎn)品flavor時(shí)应闯,可以覆蓋任何defaultConfig屬性。
有關(guān)可在此塊中配置的屬性的更多信息挂捻,請(qǐng)參閱ProductFlavor碉纺。

/**
     * applicationId uniquely identifies the package for publishing.
     * However, your source code should still reference the package name
     * defined by the package attribute in the main/AndroidManifest.xml file.
     */
    applicationId 'com.example.myapp'
    // Defines the minimum API level required to run the app.
    minSdkVersion 15
    // Specifies the API level used to test the app.
    targetSdkVersion 28
    // Defines the version number of your app.
    versionCode 1
    // Defines a user-friendly version name for your app.
    versionName "1.0"
      .............. 
在渠道配置這里可以對(duì) config 的屬性進(jìn)行覆蓋 比如這里進(jìn)行的覆蓋就是 appid  
productFlavors {
    free {
      dimension "tier"
      applicationId 'com.example.myapp.free'
    }
    paid {
      dimension "tier"
      applicationId 'com.example.myapp.paid'
    }
  }

buildTypes{}
您可以在模塊級(jí) build.gradle 文件的 android 代碼塊內(nèi)部創(chuàng)建和配置構(gòu)建類型。當(dāng)您創(chuàng)建新模塊時(shí)刻撒,Android Studio 會(huì)自動(dòng)為您創(chuàng)建調(diào)試和發(fā)布這兩種構(gòu)建類型骨田。盡管調(diào)試構(gòu)建類型不會(huì)出現(xiàn)在構(gòu)建配置文件中,Android Studio 會(huì)為其配置 debuggable true疫赎。這樣盛撑,您可以在安全的 Android 設(shè)備上調(diào)試應(yīng)用并使用通用調(diào)試密鑰庫(kù)配置 APK 簽署。

如果您希望添加或更改特定設(shè)置捧搞,您可以將調(diào)試構(gòu)建類型添加到您的配置中抵卫。以下示例為調(diào)試構(gòu)建類型指定了 applicationIdSuffix狮荔,并配置了一個(gè)使用調(diào)試構(gòu)建類型中的設(shè)置進(jìn)行初始化的“staging”構(gòu)建類型。

buildTypes {
        debug {
            minifyEnabled false
        }
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
構(gòu)建變體

buildType自定義變量

buildType 還可以做到對(duì) buildConfig 文件寫入變量來(lái)控制一些字段
在這里設(shè)置的字段 最終會(huì)被編譯到 buildConfig.java中


buildConfig

項(xiàng)目中就可以直接使用 buildConfig 文件來(lái)讀取某些構(gòu)建配置共代碼層使用了介粘。

productFlavors {}
創(chuàng)建產(chǎn)品風(fēng)格與創(chuàng)建構(gòu)建類型相似:只需將其添加到構(gòu)建配置中的 productFlavors 代碼塊并加入所需的設(shè)置即可殖氏。產(chǎn)品風(fēng)格支持與 defaultConfig 相同的屬性,這是因?yàn)?defaultConfig 實(shí)際上屬于 ProductFlavor 類姻采。這意味著雅采,您可以在 defaultConfig 代碼塊中提供所有風(fēng)格的基本配置,每種風(fēng)格均可更改任何這些默認(rèn)值慨亲,例如 applicationId婚瓜。

// Specifies one flavor dimension.
    flavorDimensions "version"
    productFlavors {
        demo {
            // Assigns this product flavor to the "version" flavor dimension.
            // This property is optional if you are using only one dimension.
            dimension "version"
            applicationIdSuffix ".demo"
            versionNameSuffix "-demo"
        }
        full {
            dimension "version"
            applicationIdSuffix ".full"
            versionNameSuffix "-full"
        }
    }
image.png

當(dāng)你配置了產(chǎn)品風(fēng)格以后 buildVariant 會(huì)變成上圖所示的樣子
buildType 與 ProductFlavor 進(jìn)行了交叉組合
他們的區(qū)別是什么呢?
一般情況 buildType 是為了構(gòu)建形式進(jìn)行的設(shè)定刑棵,比如是 debug 還是 release 版本巴刻,這兩種情況有些不同的配置比如服務(wù)器地址或。
productFlavor 更像是針對(duì)構(gòu)建完成后產(chǎn)品的差異而進(jìn)行的配置蛉签,比如我需要構(gòu)建一個(gè) 某平臺(tái)的 apk 包胡陪,這個(gè)平臺(tái)要求的 minsdk 與其他不同 那么我在這里設(shè)置一個(gè)不同的值,兩個(gè)版本的 apk 包碍舍,這時(shí)也可以使用 productFlavor 進(jìn)行設(shè)置柠座,我個(gè)人的理解是 buildType 是配置怎么構(gòu)建,而 productFlavor 是構(gòu)建給誰(shuí)片橡。

splits{}

splits {
    // Configures multiple APKs .
    ...    
  }

另一個(gè)跟打包相關(guān)的塊是 splits 分包塊
這個(gè)塊里面有兩個(gè)常用的字段
1妈经、abi cpu 架構(gòu)

splits {

    // Configures multiple APKs based on ABI.
    abi {
      // Enables building multiple APKs per ABI.
      enable true
      // By default all ABIs are included, so use reset() and include to specify that we only
      // want APKs for x86 and x86_64.
      // Resets the list of ABIs that Gradle should create APKs for to none.
      reset()
      // Specifies a list of ABIs that Gradle should create APKs for.
      include "x86", "x86_64"
      // Specifies that we do not want to also generate a universal APK that includes all ABIs.
      universalApk false
    }
  }

2、density 屏幕分辨率


splits {
    // Configures multiple APKs based on screen density.
    density {
      // Configures multiple APKs based on screen density.
      enable true
      // Specifies a list of screen densities Gradle should not create multiple APKs for.
      exclude "ldpi", "xxhdpi", "xxxhdpi"
      // Specifies a list of compatible screen size settings for the manifest.
      compatibleScreens 'small', 'normal', 'large', 'xlarge'
    }
  }
設(shè)置 splits density 時(shí)打包結(jié)果

我們?cè)偌尤?abi 的部分

 splits {

        // Configures multiple APKs based on screen density.
        density {
            // Configures multiple APKs based on screen density.
            enable true
            // Specifies a list of screen densities Gradle should not create multiple APKs for.
            exclude "ldpi", "xxhdpi", "xxxhdpi"
            // Specifies a list of compatible screen size settings for the manifest.
            compatibleScreens 'small', 'normal', 'large', 'xlarge'
        }
        abi {
            // Enables building multiple APKs per ABI.
            enable true
            // By default all ABIs are included, so use reset() and include to specify that we only
            // want APKs for x86 and x86_64.
            // Resets the list of ABIs that Gradle should create APKs for to none.
            reset()
            // Specifies a list of ABIs that Gradle should create APKs for.
            include "x86", "x86_64"
            // Specifies that we do not want to also generate a universal APK that includes all ABIs.
            universalApk false
        }
    }

image.png

配置了這些后 如果我們部署測(cè)試機(jī)是怎么樣的锻全?
log

看到 執(zhí)行了 assembleDemoDebug 也就是 執(zhí)行了 buildTpye debug
productFlavor demo 的組合 而在 build/output/apk中 我們看到了
image.png

所以這是先打出所有符合條件的包 再將符合規(guī)則的包部署到測(cè)試機(jī)上狂塘。

除了 splits 對(duì)包進(jìn)行區(qū)分在 productFlavor 也可也達(dá)到同樣的效果

   // Specifies one flavor dimension.
    flavorDimensions "version","abi"
    productFlavors {
        arm{
            dimension "abi"
            ndk {
                abiFilters "arm64-v8a", "armeabi", "armeabi-v7a"
            }
        }
    }

這樣在指定 buildVariant 時(shí)就能直接指定 abi 架構(gòu)了



(但是這個(gè)不能與 splits 的 abi 同時(shí)設(shè)置,會(huì)報(bào)沖突錯(cuò)誤)
ERROR: Conflicting configuration : 'armeabi-v7a,armeabi,arm64-v8a' in ndk abiFilters cannot be present when splits abi filters are set : x86_64,x86
Affected Modules: app
sourceSets{}


sourceSets配置

sourceSets 的配置基本就是指定源文件的路徑,通過(guò)添加一些配置文件的變量鳄厌,可以達(dá)到根據(jù)配置編譯不同的類文件或資源文件荞胡,在模塊化項(xiàng)目中可以做到動(dòng)態(tài)配置 lib木塊功能及界面。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末了嚎,一起剝皮案震驚了整個(gè)濱河市泪漂,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌歪泳,老刑警劉巖萝勤,帶你破解...
    沈念sama閱讀 218,036評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異呐伞,居然都是意外死亡敌卓,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門伶氢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)趟径,“玉大人瘪吏,你說(shuō)我怎么就攤上這事∥锨桑” “怎么了掌眠?”我有些...
    開封第一講書人閱讀 164,411評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)幕屹。 經(jīng)常有香客問我蓝丙,道長(zhǎng),這世上最難降的妖魔是什么望拖? 我笑而不...
    開封第一講書人閱讀 58,622評(píng)論 1 293
  • 正文 為了忘掉前任渺尘,我火速辦了婚禮,結(jié)果婚禮上靠娱,老公的妹妹穿的比我還像新娘沧烈。我一直安慰自己掠兄,他們只是感情好像云,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蚂夕,像睡著了一般迅诬。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上婿牍,一...
    開封第一講書人閱讀 51,521評(píng)論 1 304
  • 那天侈贷,我揣著相機(jī)與錄音,去河邊找鬼等脂。 笑死俏蛮,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的上遥。 我是一名探鬼主播搏屑,決...
    沈念sama閱讀 40,288評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼粉楚!你這毒婦竟也來(lái)了辣恋?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,200評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤模软,失蹤者是張志新(化名)和其女友劉穎伟骨,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體燃异,經(jīng)...
    沈念sama閱讀 45,644評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡携狭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了回俐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片逛腿。...
    茶點(diǎn)故事閱讀 39,953評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡壹瘟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出鳄逾,到底是詐尸還是另有隱情稻轨,我是刑警寧澤,帶...
    沈念sama閱讀 35,673評(píng)論 5 346
  • 正文 年R本政府宣布雕凹,位于F島的核電站殴俱,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏枚抵。R本人自食惡果不足惜线欲,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望汽摹。 院中可真熱鬧李丰,春花似錦、人聲如沸逼泣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)拉庶。三九已至嗜憔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間氏仗,已是汗流浹背吉捶。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留皆尔,地道東北人呐舔。 一個(gè)月前我還...
    沈念sama閱讀 48,119評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像慷蠕,于是被迫代替她去往敵國(guó)和親珊拼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評(píng)論 2 355